ナム山

家最高 今年一年でサックスが吹けるようになるか観測中

テンプレートのテキストを一部差し替えて使いまわす - ページ遷移のポップアップテキストを作成する

先日、外部リンクをクリックした際ポップアップにテキストを表示する、という案件を対応した。
遷移先は別ドメインである旨を表示して、遷移する or 留まるリンクをクリックさせるというものだ。
免責事項の表示や、離脱防止などによく使われている。
すでにモーダルプラグインを使用していたので、それらを組み合わせて使おうと思ったが、テンプレ文を何度も書くのが好ましくないと思いjavaScriptでモーダルの表示先htmlを処理させることにした。

仕様

  • ドメインに遷移するリンクをクリックした際にポップアップテキストの表示
  • テキストはテンプレ文+遷移先のリンク+キャンセルするリンク

やりたいこと

  • テンプレートのリンクに、クリック先のurlを差し替えて使いまわしたい
  • 既存のモーダルプラグインへの繋ぎこみ

aタグのhrefでターゲットを指定するタイプのモーダルプラグインを想定。
とりあえず特定のdivにブチ込むところまで。

HTML

<a href="#dest00" id="test00" data-href="http://test00" class="js-dest">リンク00</a>
<a href="#dest01" id="test01" data-href="http://test01" class="js-dest">リンク01</a>

<!-- modalの表示先 -->
<div id="dest00"></div>
<div id="dest01"></div>

JavaScript

temp = '遷移先リンクは<a href=\"\[get_item1\]\" target=\"_blank\">\[get_item1\]<\/a>です、キャンセルする場合のリンク<a href=\"\[get_item2\]\">\[get_item2\]<\/a>';
var back = window.location.href;

$('.js-dest').each(function(){
  var dest = $(this).attr('data-href');//遷移先
  var tgt = $(this).attr('href');//テキスト表示先
  var new_temp = temp.replace('\[get_item1\]',dest).replace('\[get_item2\]',back);//テンプレートから差し替えたテキスト
  $(function(){
    $(tgt).append(new_temp);
  });
});

ひとまず想定通りDOMが生成されたのでOK。
これ、そのまま外部リンクをクリックしてもモーダルの表示はそのままなので、そこからプラグインに用意されていたコールバックやイベントで味付けして実装した。
キャンセルでただ閉じるのでなく再度そのページを読み込ませたのは案件の仕様の名残。
自由度の高い案件であればこれぐらいで良さそうだけど、ガチガチの案件ならばJSONとかでもっとちゃんと処理する必要がありそう。
ひとまず.replaceが複数回使用できるの知らなかったので良い勉強になった。

経過観測6〜2019年を振り返って〜

振り返りと変化

2020年になった。今年もよろしくお願いします。

成長記録として始めたブログなので目標の振り返りを。
今回は2019年の総振り返り。
昨年の目標はこういったものだった。

  • 英語 - 簡単な日常会話ができるようになる + 観たい映画を字幕なしで鑑賞できるようになる
  • プログラミング - jQueryを極める + 他の言語にも手を出す
  • ギター - 難しい課題曲を弾けるようになる + スイープの習得
  • サックス - ライブで使えるくらいになる(初心者脱出)

4つの大目標に対し、10日区切りでクリアできる簡単な目標も設定した(4分野 * 8項目 = 32項目)
さらに各分野、日々のルーティンも習慣化を目指した(4分野)。
詳細はこちら
numb-yam.hatenablog.com
先に数字から。

  • 英語 - ルーティン:クリア 小項目 4/8クリア
  • プログラミング - ルーティン:60/365 小項目 1/8クリア
  • ギター - ルーティン:180/365 小項目 1/8クリア
  • サックス - ルーティン:30/365 小項目 1/8クリア

数値で見ると散々な結果だ。
しかし感覚値でいえば、毎日何かしらやろうという気持ちになっていたのはよかった。
ぐうたらな過去の自分に比べればかなりの収穫だ。
そもそも365日かけて楽しみつつ、1年かけて習慣化することを意識できたのは超褒めてる。
途中でレベルを上げたり、再設定したり風呂敷を広げすぎた感は否めないので2020年はこれを継続してブラッシュアップしたい。

各項目の振り返り

英語

一番頑張った、学習のしやすさもあって勉強そのものが趣味になったのが収穫。
パラメーターに分解して循環するように勉強する方法を見つけられたのも良かった。
サボったりしたけど、365日分日記を書いた。
800語近く単語帳に登録して、そのフラッシュカードを10,000回こなした。
鍛えようがわからなかったリスニングもいいアプリを見つけられたおかげで少し聞き取れるようになったと思う。
今年はスピーキングの方法を見つけて鍛錬できるようになりたい。

プログラミング

実のところはもう少し取り組めていたけど、あまりにざっくり進めていたのもあって厳し目に。
事実、動画講座とかは全然やれてなかった...。

ギター

大きい目標として、課題曲は弾けるようになったのは良いかと。
暇があれば課題フレーズを弾いたし、自分に伸び代があるのがわかって嬉しかった。
バンドで長回しのソロを振られる機会があって、思いの外レスポンスよくできたと思う。
こちらもざっくりと進めすぎたし、スイープが弾けているかといえば全然なのでもうちょっと分解して今年は鍛錬したい。

サックス

結局全然できなかった。
時間でいえば15時間程度。
今年は無理矢理にでも練習のようなライブを自分で入れてしまうことにした。
やるぞ、気合い入れるぞ。

2020年の目標

足りないところを伸ばす、ブラッシュアップ、そして去年からの引き継ぎといった具合に。
2019年は知らないことを広げる年だったので、今年は広げながらも深める年にしたい。

英語

【ルーティン:2019年の英語日記をブラッシュアップする / 単語帳】
各項目

  1. 日常会話の10分番組を見る
  2. reading - 好きなミュージシャンの英語wikipediaを読む
  3. listening - 英語のリスニングアプリを50題
  4. speaking - 英語の発音 + リスニング動画を全て見る
  5. listening - 英語のスピーチ動画を見る
  6. reading - 海外のリファレンスを読む
  7. reading - 英語のコラムを読む
  8. speaking - 英会話教室に通って見る

去年の日記をブラッシュアップしたり、英単語を英英で勉強してライティングを鍛えられることがわかった。
なので今年は他のスピーキング、リスニング、リーディングを進めたい。
リスニングとスピーキングのトレーニングには、ニック式英会話がいまの自分にはピッタリ。
www.youtube.com
動画中でも説明しているけど、発音できれば聴くことができるというのは本当で、
つまり自分の中にサンプルがなければ照合しようがないのである。
どの学習にも当てはまることで、そのことを知れたのは良かった。

プログラミング

【ルーティン:1記事読む】
各項目

  1. JavaScriptのテキストを1冊再読
  2. UdemyのJavaScript講座を修了する
  3. UdemyのRuby on Rails講座を修了する
  4. jQueryの効率化、スピードアップ、トラバース系の技術向上
  5. HTTP(GET,POST)/cookie,session/Ajax/PHPについて復習
  6. Reactの導入
  7. Vue触って見る
  8. 簡単なアプリの作成

定量化しにくい事ばかりだけど、とりあえずJavaScriptのテキストを再読して各項目を復習することにした。
新しく始めることはRuby on RailsとReact/Vue。
JavaScriptやその他通信周りの学んだことは記事にする。
裏目標として2018年度に10記事、2019年に20記事書いたので今年は30記事書くことにした。
本当に小さな一歩でも、楽しさをキープしてじっくり続けられるように頑張る。

ギター

【ルーティン:苦手フレーズを弾く / コピーしたり、移調して使ったりする】
各項目

  1. 課題曲を70%のスピードで弾く / スイープの基礎動画こなす
  2. 音楽理論のテキストをこなす
  3. 課題曲を80%のスピードで弾く / Jazzの理論動画も勉強する
  4. ギターフレーズのテキストをこなす
  5. 課題曲を90%にスピードで弾く / 音楽理論の動画も勉強する
  6. 1曲コピーする / 早弾きの基礎動画こなす
  7. 課題曲を100%にスピードで弾く / カッティングの基礎練もやる
  8. 1曲コピーする / 興味のある理論動画もっと見て見る

昨年一年間自分が何を弾くのか観察するきっかけになったんだけど、自分は基礎練が異様に好きなことがわかった。
弾いてるだけで楽しいのでルーティンは意識的に苦手なフレーズの練習をすることにした。
あと結局のところギターも引き出しの多さがはっきりと実力に現れることがわかったのでコピーをすることにした。
技自体を磨くのと、技を広げるのが目標。
体の鍛錬と、頭の鍛錬も同時に行いたい。
まずは片手間で良いのでyoutubeでいろんな理論を頭に入れていく。
主な理論は普段読んでいる音楽理論のテキストを1周して、それを体に馴染ませる。

サックス

【ルーティン:口輪筋のトレーニング】
各項目

  1. 音を安定して出す / アンブシュア
  2. キラキラ星とか吹いてみる / トリルとスラーの基礎練
  3. テキストを半分こなす / スケール練習、半音練習
  4. 音を太くする
  5. テキストを半分こなす / 音がひっくり返らないようにスケール練習をする
  6. 簡単な曲を1曲吹けるようになる
  7. セッションで使って見る
  8. ライブで使えるように曲に取り入れる

こちらも不自由なく使える程度に仕組みを知る / 太い音で、ひっくり返らず、運指できるようにする
といった具合に頭と体バランスよく鍛錬したい。
情けないことに打席に立たないとなんもできないことがわかったので、今年は無理矢理にでもライブの予定を入れてしまおうと思う。
どうなることやら...。

2019年を振り返って

小さな結果が嬉しかった。何かを毎日続けても、すぐには結果が出ない。
半年ほど続けるとようやく芽が出て、複利的に飛躍して成長を感じられるようになる。
その自信に支えられて1年頑張れたし、今確実に成長を感じられている。
面白いことに、ちょうど良いタイミングでひとから舞台や役割を与えられることの多い年だった。
それは意識して取り組んでいるからこそそう思えるのかも知れないけど、準備した人間しかチャンスをつかめないというのは実感としてわかった。
きっとこんなに成長した成長したって言えるのはまだ自分のレベルが低いからだろうし、
笑っちゃうようなことかも知れないけど確実に努力した自分の足跡がこんなに尊いものだとは思わなかった。

わかったこと

  • なにごとも数(サンプル量)が必要
  • 復習が学習のキモ
  • 全く手応えがない学習は一つレベルを落としてみることが大事

こうしてみると頭と体のバランスとか、目標の立て方自体が理にかなったものになってきた。
今年も頑張るぞー

HTMLとCSSでボックスが重なった表現をする

f:id:numb_yam:20191226184727j:plain
先日変わったデザインのテキストボックスを作る機会があったのでメモ。

概要

・背景が透過したボックスがふたつ重なった形状
・文章量は可変

デモコード

HTML
<div class="c-boxs">
  <div class="c-boxs__item">テキストテキスト</div>
  <div class="c-boxs__item">テキストテキスト</div>
  <div class="c-boxs__item">テキストテキスト</div>
</div>

CSS

body{
  background: #92CAB8;  
}
.c-boxs{
  display: flex;
  justify-content: space-between;
	&__item{
		position: relative;
		display: block;
		width: 30%;
		min-height: 100px;
		padding: 10px;
		margin-right: 10px;
		background: rgba(240,240,240,.9);
		&::before{
			content: '';
			display: block;
			position: absolute;
			top: 10px;
			left: 10px;
			z-index: -1;
			width: calc( 100% - 10px);
			height: calc( 100% - 10px);
			border-right: 10px solid rgba(220,220,220,.6);
			border-bottom: 10px solid rgba(220,220,220,.6);
		}
	}
}

工夫した点

はじめは単純にボックスをずらして重ねれば良いと思っていた。
しかし背景が透過のため、そのままだと重なりが見えてしまう。
f:id:numb_yam:20191226184741j:plain
そこで前面のボックスと同じものを用意し、その要素のボーダーで表現することにした。
地味にボーダーもアルファ効くの初めて知った。

.detach()メソッドについて

先日ライブラリのjsファイルを覗いていた際に見慣れないメソッドを見つけたので調べてみた。

機能

.remove()と似ているが、削除したDOM要素を保持することができる。
js.studio-kingdom.com

detachの場合は関連付けられているjQueryの情報を削除後も保持します。
つまりオブジェクトとして保持して後から再利用できる。

参考

qiita.com

非常に参考になる。
いちいちDOM要素を作成しないので、動作が非常に速く」なるのも良い。

使い道

detachは「引き離す」という意味。
上記参考サイトにもある通り、削除というよりもDOM上で表示/非表示をコントロールしたいときに本領を発揮しそう。
他には、レスポンシブサイトで微妙にテキストのレイアウトが違う時とか地味に役立ちそう。

レイアウトが変わる時の対応

以前はHTMLに二つ書いて、cssで表示切り替えしたこともあるけどあまり好きではないし、よくないと思う。
かといってわざわざレンダリングに負荷かけるのも良い気持ちはしないが...。

こちらは以前、動かしたい要素基準でHTMLの中を移動させたコード。
構造にもよるけど処理の時間がかかると思う。

w = $(window).innerWidth();
function txt_switch(){
	$("動かしたい要素").each(function(){
		var tgt = $(this).siblings('追加したい先');
		if( w <= 767 ){
			$(tgt).after($(this));
		}else if( w > 767 ){
			$(tgt).before($(this));
		}
	});
}


上でイメージした、各HTML要素基準で内部の構造を入れ替えるコード。
とりあえず動いたけど、トラバース系メソッドも一回ちゃんとさらい直して挙動が早いコードを意識できるようにしたいと思った。

$(function(){
	w = $(window).innerWidth();
	var wrap = $('親要素');
	if( w <= 767 ){
		$(wrap).each(function(){
			var tgt = $(this).find('対象');
			var dest = $(this).find('追加先');
			var val = $(tgt).detach();
			$(dest).append(val);
		});
	}
});

bxsliderでリンクが効かない - 失敗1 -

うまくいった記事はあるけど調査中に失敗したことや、間違った対処法を書いた記事ってあまり見ないなと最近思い、デバッグの最中に陥った問題も書くことにしようと思った。
堂々巡りしている人の助けになれば幸い。

概要

スライダーとモーダルを組み合わせた特殊な要件の構築中、スマホでスライダーの中のモーダルが立ち上がらなくなった。
さらにタップするとスライダーの操作も効かなくなってしまう。
モーダルはaタグをクリックすることで発動する。

症状が出た条件

内容

正解

原因は「aタグのタッチイベントが認識されていない」だった。
こちらのブログを参考に解決。
ありがとうございます。
bxSliderのスライド内のリンクが効かなくなった際の対処方 | ウェブマガジン カミナリ | 鳥取県米子市のホームページ制作・広告代理店・デザイン

イベントの解釈違いを矯正する対応なので、仕様が厳しい案件の場合は要注意。
Chromeのアップデートで変わる可能性も大いにあり。
以下、調査の足取り。

仮説

調査にあたり立てた仮説

  • cssの擬似要素が邪魔していないか
  • jsの処理タイミングの問題か
  • 発火元のDOMがjQueryで操作される(スライダーに構築される)ことが原因なのか - 動的要素とイベントの問題
仮説1 - 違ったけどきっかけになった

cssの擬似要素が邪魔していないか
よくあるケース。次項の処理順序をまず疑ったがシンプルに行こう、と思い開発モードでソースをさらう。
というのもSPで長押ししてもリンク要素を長押ししたときの挙動と違い、コピーコマンドが出なかったので「クリックできていない」と判断したから。
結果、覆っている不可視オブジェクトなどはなかったが、クリックした際にボタン(prev/next)に'.disabled'というclassが付与されていることに気づく。
bxsliderの中にある'Event handler for "touchstart"'の項目からコメントアウトして対応。

注:これも根本的な解決ではなく、スワイプでの挙動を制限しているので本来あまり良くはない。
結論:惜しいところまでいけていた

仮説2 - 違ったけど前向きに調査できた

jsの処理タイミングの問題か
これもよくあるケース。ready/load 各タイミングで必要なものだけ動くように微調整。
そもそも一部のiPhoneでちゃんと動くのでこれが原因とは考えにくい。
代わりにダラダラ書いていたものを配列化したり関数化したりしてデバッグしやすくした。
デバッグしやすいコードは心が折れにくくなって良い...。
結論:綺麗なコードだと調査もしやすい

仮説3 - 見当違い

発火元のDOMがjQueryで操作される(スライダーに構築される)ことが原因なのか - 動的要素とイベントの問題
冷静に考えればPCや一部のiPhoneでまともに動いているのだからそもそも違うはず。
それなのにためしに動的に追加したトリガーから、イベントが発火しないのを見て震えたりしていた。
俺は一体何をしていたんだ...。

ただ、動的要素に対し関数を初期化できるのか?(日本語あっているのか)は調査したいと思ったので収穫とする。
結論:完全な絶望のマッチポンプ

解決順序
  • コンソールエラーが出ない
  • SPでコピーコマンドが出ない
  • スライダー領域をタップしただけでタッチイベントが不本意に走っていた

以上から「そもそもaタグのイベントが走っていない」と気づいて正解にたどり着いた。

よかった点と収穫

  • 起きているイベントをclassから逆引きしたこと
  • 初期化から疑ったこと(jsの仕組みをさらって再理解が深まった)
  • 動的要素に対する関数の初期化を調べたいと思った

全体の感想として、心が折れなくなったのはでかい。
何かしら解決の糸口はきっとあると経験で知っていること、たくさんの経験から細分化していろんな面から試行できること。
それがまた新たに知識と方法論を与えてくれるのでこういった「うまくいかなかったケース」もたくさん書いていこうと思った。

hoverした時に説明文が出てくるタイルパターンをCSSのみで実装する

f:id:numb_yam:20191129144020p:plain
よくあるタイル型レイアウトで、hoverした時に説明文が出てくるCSSとHTML。
コーポレートサイトのトップページなどでよく見る。
■HTML

<div class="container">
  <div class="items">
    1
    <span class="items__info">説明文</span>
  </div>
  <div class="items">
    2
    <span class="items__info">説明文</span>
  </div>
  <div class="items">
    3
    <span class="items__info">説明文</span>
  </div>
  <div class="items">
    4
    <span class="items__info">説明文</span>
  </div>
  <div class="items">
    5
    <span class="items__info">説明文</span>
  </div>
  <div class="items">
    6
    <span class="items__info">説明文</span>
  </div>
</div>

CSS

.container{
  display: grid;
  grid-gap: 10px;
  grid-template-columns: 1fr 1fr 1fr;
  grid-template-rows: 1fr 1fr 1fr 1fr;
}
.items{
  position: relative;
  overflow: hidden; /* はみ出た部分を非表示に */
  display: flex;
  align-items: center;
  justify-content: center;
  box-sizing: border-box;
  padding: 10px;
  border-radius: 10px;
  border: solid 4px #ccc;
  background: #ddd;
  max-width: 100%;
  min-height: 100px;
  &__info{
  	/* 基本は枠外に出して見えなくする */
    position: absolute;
    top: 100%;
    display: flex;
    justify-content: center;
    align-items: center;
    width: 100%;
    height: 100%;
    background: rgba(0,0,0,.8);
    transition: .3s;
    color: #fff;
  }
  &:hover{
    >span{
    	top: 0;
    }
  }
}

ついでなのでgridパターンでやってみた。
細かなデザインはお任せるするが、今回のメインはabsoluteの位置で操作する点。

解説

このパターンの簡単な仕組みは以下

  • absoluteでカード全体に覆いかぶさるように表示
  • それを枠外に出して非表示にしておく
  • 後はhoverしたら位置を戻す

jsでやっても良いが面倒なのでCSSでやることが増えた。
absoluteで幅も高さも100%で用意した領域を、transitionをかけた動きで操作する。
top: 100%;だと高さを計算する必要もなく領域外へ追いやることができるので便利。
備忘録も兼ねて。

グリッドレイアウトの基礎 - display: grid; 触ってみた -

f:id:numb_yam:20191126163313p:plain
グリッドレイアウトのLP案件を担当したのでこれを機に手を出してみた。

グリッドレイアウトの基本

大まかな流れ

  • 親にdisplay: grid;を設定
  • 親に縦横の比率、grid間のスペースを設定する
  • 子要素で、最小単位より大きくしたいときは追加で設定する

具体的な設定内容

■HTML

<div class="container">
  <div class="items items--l1">Large 1</div>
  <div class="items">1</div>
  <div class="items">2</div>
  <div class="items">3</div>
  <div class="items">4</div>
  <div class="items">5</div>
  <div class="items">6</div>
  <div class="items">7</div>
  <div class="items">8</div>
  <div class="items items--l2">Large 2</div>
</div>

CSS

.container{
  display: grid;/* grid要素の設定 */
  grid-gap: 10px;/* grid要素間の隙間 */
  grid-template-columns: 1fr 1fr 1fr;/* グリッドの横幅の比率 */
  grid-template-rows: 1fr 1fr 1fr 1fr;/* グリッドの高さの比率 */
}
.items--l1{
  grid-column: 1 / 2;
  grid-row: 1 / 3;
}
.items--l2{
  grid-column: 3 / 4;
  grid-row: 3 / span 2;
}
/* 以下はレイアウト調整 */
.items{
  display: flex;
  align-items: center;
  justify-content: center;
  box-sizing: border-box;
  padding: 10px;
  border-radius: 10px;
  border: solid 4px #ccc;
  background: #ddd;
}
メモ

grid-template-columns/grid-template-rowsは横、縦の子要素の割合を設定する。
px/%/fr(比率)で設定可能。
frは初見だったが、面倒くさければ上記のように何マス*何マスかだけ設定してやって、
イレギュラーな方をcssで詳細に指定しても良さそう。
www.webcreatorbox.com
grid-column/grid-rowは対象のグリッドの始点/終点を横縦両方で設定する。
エクセルのセル、座標指定のようなもの。
grid-row: n / span n;のようにspanに続けて「そこから何単位」と指定してやることもできる。

使って見た印象

display: flex;に慣れていたらわかりやすい。

  • 親要素にどのような縦横のグリッド組みか、比率やグリッド間の設定をする。
  • 次にイレギュラーな要素のcssを設定する。

凝ったレイアウトでなければこの程度で上のようなデザインは簡単にできた。
あと意外だけど子要素(ここでいう.items)にmax-width: 100%;をつけてやれば内容に限らずレイアウト崩れに対応できる。
親要素の設定ですでに比率設定されているので、そのmax幅を割り当ててやれば良い、ということだろう。
developer.mozilla.org
qiita.com
また、参考サイトにある通り、レスポンシブ対応する場合

.container {
	grid-template-columns: 1fr;
	grid-template-rows: auto;
}

で100%幅で落としていける。

あとリファレンスの中に興味深いプロパティがあったのでついでに調べた
minmax()
developer.mozilla.org
形式は以下
minmax( [ | | | min-content | max-content | auto ] , [ | | | min-content | max-content | auto ] )
min , maxをコンマつなぎで引数をもたせてやる。
各要素はlength/percentage/flexそれぞれ織りまぜることができるらしい。
CSSの関数も結構進化してきているな〜