やりたかったこと
- 画像を含んだ要素をappendする
- appendされた画像がすべてロードされたあとに関数を実行する
- その関数で、imgを含めた要素の高さを取得する
つまづいたところ
通常ならappendしたらそのまま次の処理でheight()すれば、要素の高さを取得することができるが、画像をappendしたときは画像がロードされたのを見届けなければ、高さがうまくとれない。
それは、画像を子孫に含んだ要素も同じです。
リロードするとキャッシュされたものを拾ってくれるので、一見するとうまく処理されているように見えるトラップつきだった。
失敗コード
appendしてすぐにmatch_height_byChildElems('.js-add-faceImgs');
しているコードです。
$(function () {
var thumbnails = ['taro', 'jiro', 'saburo', 'shiro', 'goro', 'tanjiro']
for (var i = 0; i < thumbnails.length; i++) {
var iconURL = '/img/icon_face_' + thumbnails[i] + '.png';
html = '<li>';
html += '<img src="' + iconURL + '" alt="">';
html += '</li>';
var $elm = $(html);
$('.js-add-faceImgs').append($elm);
}
match_height_byChildElems('.js-add-faceImgs'); // ココ!
});
/**
* 子要素の最大の高さを計算して、親要素の高さを指定する
* @param {String} className 親クラス名*/
function match_height_byChildElems(className) {
var maxHeight = 0;
$(className).children().each(function(){
var thisHeight = $(this).height();
console.log($(this), thisHeight)
maxHeight = maxHeight <= thisHeight ? thisHeight : maxHeight;
});
$(className).height(maxHeight);
}
解決方法
追加した要素の長さとloadCounter
の値が同じ = 処理完了!
として、そのときにmatch_height_byChildElems('.js-add-faceImgs')
を呼び出しています。
これで、setTimeout()など当てずっぽう数字ではなく、指定のimgすべてがロード完了したときに関数を呼び出すことができます。
成功コード
$('.js-add-faceImgs img').each(function(){~~
を追加して、imgのロード完了をカウントしています。
$(function () {
var thumbnails = ['taro', 'jiro', 'saburo', 'shiro', 'goro', 'tanjiro']
for (var i = 0; i < thumbnails.length; i++) {
var iconURL = '/img/icon_face_' + thumbnails[i] + '.png';
html = '<li>';
html += '<img src="' + iconURL + '" alt="">';
html += '</li>';
var $elm = $(html);
$('.js-add-faceImgs').append($elm);
}
// imgのロードが完了したらマッチハイトさせる
// ココ!
var loadCounter = 0;
$('.js-add-faceImgs img').each(function(){
$(this).load(function(){
loadCounter++;
if (loadCounter === $('.js-add-faceImgs img').length) {
match_height_byChildElems('.js-add-faceImgs');
}
});
});
});
/**
* 子要素の最大の高さを計算して、親要素の高さを指定する
* @param {String} className 親クラス名*/
function match_height_byChildElems(className) {
var maxHeight = 0;
$(className).children().each(function(){
var thisHeight = $(this).height();
maxHeight = maxHeight <= thisHeight ? thisHeight : maxHeight;
});
$(className).height(maxHeight);
}
余談
こう書いたほうがスッキリするかもです。
// imgのロードが完了したらマッチハイトさせる
var loadCounter = 0;
$('.js-add-faceImgs img').each(function(){
$(this).load(function(){
loadCounter++;
var loadComplete = (loadCounter === $('.js-add-faceImgs img').length);
if (loadComplete) match_height_byChildElems('.js-add-faceImgs');
});
});