🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
Firefox

Mozilla Foundationによって作られた無料、オープンソース、クロスプラットフォームなウェブブラウザ

jQuery

jQueryは、JavaScriptライブラリのひとつです。 簡単な記述で、JavaScriptコードを実行できるように設計されています。 2006年1月に、ジョン・レシグが発表しました。 jQueryは独特の記述法を用いており、機能のほとんどは「$関数」や「jQueryオブジェクト」のメソッドとして定義されています。

CSS

CSSはXMLやHTMLで表現した色・レイアウト・フォントなどの要素を指示する仕様の1つです。

Q&A

解決済

1回答

944閲覧

FirefoxとjQueryで画像を含む要素を複製した時に高さが正しく取得できない

退会済みユーザー

退会済みユーザー

総合スコア0

Firefox

Mozilla Foundationによって作られた無料、オープンソース、クロスプラットフォームなウェブブラウザ

jQuery

jQueryは、JavaScriptライブラリのひとつです。 簡単な記述で、JavaScriptコードを実行できるように設計されています。 2006年1月に、ジョン・レシグが発表しました。 jQueryは独特の記述法を用いており、機能のほとんどは「$関数」や「jQueryオブジェクト」のメソッドとして定義されています。

CSS

CSSはXMLやHTMLで表現した色・レイアウト・フォントなどの要素を指示する仕様の1つです。

0グッド

1クリップ

投稿2019/10/22 00:00

編集2019/10/22 00:08

恐れ入りますが、ご教授いただければ助かります。
imgタグを複数含む要素をjQueryベースで複製するコードを実行したところ、Firefoxでは高さが正しく取得できないことがあります。以下のようなHTMLで500×500pixelの画像を10個含むul要素を複製しています。

HTML

1<!DOCTYPE html> 2<html lang="ja"> 3<head> 4 <meta charset="utf-8"> 5 <style type="text/css"> 6 * {margin: 0; padding: 0;} 7 ul {list-style: none;} 8 button {padding: 10px;} 9 </style> 10</head> 11<body> 12 <button class="copy">複製</button> 13 <ul class="images"> 14 <li><img src="images/test/01.jpg"></li> 15 <li><img src="images/test/02.jpg"></li> 16 <li><img src="images/test/03.jpg"></li> 17 <li><img src="images/test/04.jpg"></li> 18 <li><img src="images/test/05.jpg"></li> 19 <li><img src="images/test/06.jpg"></li> 20 <li><img src="images/test/07.jpg"></li> 21 <li><img src="images/test/08.jpg"></li> 22 <li><img src="images/test/09.jpg"></li> 23 <li><img src="images/test/10.jpg"></li> 24 </ul> 25 <!-- 以下のjavascriptが続きます -->

jQuery

1 <script type="text/javascript" src="js/jquery-1.9.1.js"></script> 2 <script type="text/javascript"> 3 $(document).ready(function() { 4 $('button.copy').click(function() { 5 var ul_src = $('ul.images'); 6 var ul_new1 = ul_src.clone().appendTo('body'); 7 var ul_new2 = $(ul_src.prop('outerHTML')).appendTo('body'); 8 alert( 9 'ul_src.height=' + ul_src.getHeight() + '\n' + 10 'ul_new1.height=' + ul_new1.getHeight() + '\n' + 11 'ul_new2.height=' + ul_new2.getHeight()); 12 }); 13 }); 14 $.extend(true, $.prototype, { 15 getHeight: function() { 16 return this.height(); 17 } 18 });

以下は成功した時です。※時々、成功します。
成功

以下は失敗した時です。※大抵、失敗します。
イメージ説明

Chromeでは問題が起きないのですが、それはおそらく画像のキャッシュが働いているせいかと思います。
イメージ説明

Firefoxでは要素を複製する時に、img.src先をロードする処理が走り、そのタイムラグがあるせいだと思っていますが、ロードが完了するまで待つ良い方法がわかりません。
以下のコードに変えて試してみたのですが、「too much recursion」(再帰呼び出しオーバー)となってしまいます。

jQuery

1 $.extend(true, $.prototype, { 2 getHeight: function() { 3 var imgNum = this.find('img').length; 4 var imgLoad = 0; 5 var callback = this.getHeight.bind(this); 6 while (imgLoad < imgNum) { 7 this.find('img').each(function() { 8 if (this.complete || /* for IE */ $(this).height > 0) { 9 imgLoad++; 10 } 11 }); 12 if (imgLoad == imgNum) { 13 break; 14 } 15 this.find('img').one('load', function() { 16 callback(); 17 }).load(); 18 // もしくは、setTimeoutで少し待ってみる 19 //setTimeout(callback, 100); 20 } 21 return this.height(); 22 } 23 });

どのようにすれば、画像のロード完了を待った後に、要素の高さを取得することができるでしょうか?
詳しい方にご教授いただければ。よろしくお願いいたします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

naomi3

2019/10/22 02:31

500pixel以上の画像を10枚用意してやってみましたが、当方環境ではFirefoxで高さが正しく取得できない状況は再現できませんでした。jquery-1.9.1.jsにバージョンを合わせても同様でした。
退会済みユーザー

退会済みユーザー

2019/10/22 02:39

そうですか。私が使っているFirefoxは現時点の最新の69.0.3(64ビット)ですが、問題が(必ずしもではないものの)起きます。Firefoxの設定はとくに変更しておらずデフォルトのままですが、何かそれ系で絡む話なのでしょうか。。
naomi3

2019/10/22 02:51

当方も69.0.3 (64 ビット)で、設定もとくに変更していません。Windows7, DELLの古いPCです。
退会済みユーザー

退会済みユーザー

2019/10/22 02:56

私は1年ほど前に買ったNEC製のWindows10のノートPCです。実行環境としては私の方が有利なんですね。なおさら謎になります。。
退会済みユーザー

退会済みユーザー

2019/10/29 06:55

naomi3さま、その後の余談ですが、高さが正しく取得できなかったのは、Firefoxがメモリを浪費してメモリ使用量が99%近くに達していたからだろうと思います。マシンを再起動した後は再現しなかったので。メモリの空きが少なくなると、ブラウザのキャッシュが正常に機能しなくなるでしょうから、要素を複製すると画像を取りに行く羽目になって当然かもしれません。そうした状態になると、BAの方が教えて頂いたDeferredや、setTimeout、async/await、Promiseといった非同期のコールバック形式の「後追い」で値を取得するしか方法はないようです。JavaScriptは「シングルスレッド」なので。
guest

回答1

0

ベストアンサー

ラグというのが再現させられなかったので不安なところはありますが、Deferred を使って画像のロードを待ってみるのがいいかと思います。

jQuery

1 getHeight: function() { 2 var that = this; 3 var deferred = $.Deferred(); 4 var promises = []; 5 $('img', this).filter(function() { return !this.complete; }).each(function(index, element) { 6 var deferred = $.Deferred(); 7 promises.push(deferred.promise()); 8 $(element).one('load', function() { 9 deferred.resolve(); 10 }); 11 }); 12 13 $.when.apply(null, promises).then(function() { 14 deferred.resolve(that.height()); 15 }); 16 17 return deferred.promise(); 18 }

jQuery

1 $.when(ul_src.getHeight(), ul_new1.getHeight(), ul_new2.getHeight()).then(function(src, new1, new2) { 2 alert( 3 'ul_src.height=' + src + '\n' + 4 'ul_new1.height=' + new1 + '\n' + 5 'ul_new2.height=' + new2); 6 });

https://api.jquery.com/jQuery.Deferred/
https://sekom.hatenablog.com/entry/20130705/p1

投稿2019/10/24 04:36

x_x

総合スコア13749

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2019/10/24 05:54

貴重なアドバイス、ありがとうございます! さっそく試してみたところ、問題は発生せず正常に高さを取得することができました! Deferredは全く知りませんでした。参考サイトへのリンクも貼っていただき感謝いたします。 これを機会に改めて勉強します。ありがとうございました。m(_ _)m
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.36%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問