質問をすることでしか得られない、回答やアドバイスがある。

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

新規登録して質問してみよう
ただいま回答率
85.48%
JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

jQuery

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

HTML

HTMLとは、ウェブ上の文書を記述・作成するためのマークアップ言語のことです。文章の中に記述することで、文書の論理構造などを設定することができます。ハイパーリンクを設定できるハイパーテキストであり、画像・リスト・表などのデータファイルをリンクする情報に結びつけて情報を整理します。現在あるネットワーク上のほとんどのウェブページはHTMLで作成されています。

Q&A

解決済

6回答

12783閲覧

jQuery.load()の処理後、画像のロード完了を検知したい

chibi_kuma

総合スコア85

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

jQuery

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

HTML

HTMLとは、ウェブ上の文書を記述・作成するためのマークアップ言語のことです。文章の中に記述することで、文書の論理構造などを設定することができます。ハイパーリンクを設定できるハイパーテキストであり、画像・リスト・表などのデータファイルをリンクする情報に結びつけて情報を整理します。現在あるネットワーク上のほとんどのウェブページはHTMLで作成されています。

0グッド

1クリップ

投稿2016/06/15 06:30

編集2016/06/15 12:07

jScrollというjQueryプラグインを使って、遅延ローディングを実装しようとしています。
(参考)jScroll公式 → http://jscroll.com/

jScrollプラグインの概要としては、
「分割されたページA・Bがあり、ページBの内容をjQuery.load()を使って読み込んで、ページAに追記する」
というものです。

オプションとして、jQuery.load()の処理後に、コールバック関数が呼べるようになっています。

コールバック関数内で、行いたい処理があるのですが、
「ページBをjQuery.load()を使って読み込み、ページAの要素に追記する」処理の終了後とは、
「DOMツリーの生成直後」のようで、
このタイミングでは、画像のロードが完了しておりません。

コールバック関数内で、画像のロード完了まで待ってから
処理を走らせたいのですが、どのように実装すれば良いでしょうか?

コールバック関数ではない場所で、
jQuery.event.add(window,"load",function(){ // });
を実装してみたのですが、htmlが読み込まれた初回のみ実行され、
.load()後のロード完了時には、実行されないようです。

よろしくご教授くださいますよう、お願いもうしあげます。


(補足)ページBの表示完了後イベントを掴みたかった「理由」について

制作しているページレイアウトが、以下のようになっております。

イメージ説明

レフトメニューと、メインコンテンツ部の高さを、
「jquery.heightLine.js」というjQueryプラグインにて揃えています。
(レイアウトから見直せ!というのは、諸事情によりちょっと無理なのでご勘弁ください。)

(参考)レスポンシブWebデザインに対応した「jquery.heightLine.js」
http://blog.webcreativepark.net/2013/10/21-112000.html

「jquery.heightLine.js」は、
レフトメニューと、メインコンテンツ部の要素に対し、
「style="height: XXXXpx;"」を書き込むため、高さが固定されてしまいます。

高さが固定されてしまっているので、
メインコンテンツ部に、ページBの内容が追加されたら、
「jquery.heightLine.js」をrefreshオプションをつけて呼び出すことで、
高さを再計算しなおさないと、追加された部分は隠れて見えません。

ページBの要素がDOMに追加された後で、且つ、画像が全て読み込まれたら、
メインコンテンツ部の高さが「確定」するので、
「jquery.heightLine.js」をrefresh!すればいい、などと安易に考えていた訳です。
(ホントすいません。)

しかし、画像の読み込みが完了するまで、DOMに追加しない、などの改良を行った場合、
体感的にページの表示がもっと遅くなる気がいたしますので、(想像ですが…)
遅延ローディングを実装する意味が薄れてしまいます。(本末転倒になりかねない)

実際には、
・ページBがDOMに追加され、文字などが先に表示される
・続いて、次々に画像が読み込まれ、メインコンテンツ部の高さが刻々と変わっていく
・メインコンテンツ部の高さが変わる度に、「jquery.heightLine.js」をrefresh
という実装をすべきかも知れません。
(要素の高さを常時監視って出来るのかわかりませんが…)

よって、「画像のローディング完了を検知する」のではなく、
「要素の高さの変化を検知する」か、
DOMの変化を検知する方が素直かと思い直しております。

これはこれで、敷居が結構高そうですが…。
(レンダリングコストも高そう…?)

本質問が、「jQuery.load()の処理後、画像のロード完了を検知したい」なので、
質問の主旨が変わってきてしまって。大変申し訳ありません。
他にもこんな方法があるよ、など、引き続き、アイディアをいただければ幸いです。
(一旦本質問をクローズすべきでしたら、そのようにいたします。)

よろしくお願い申し上げます。

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

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

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

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

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

guest

回答6

0

自己解決

皆様、たくさんコメントを頂き、本当にありがとうございました。

「画像のロード完了時に処理を行うべき」という考えに固執してしまった為、
質問の仕方の方向性を誤り、結局、皆様に遠回りをさせてしまう結果になりました。
本当に申し訳ありませんでした。

結論から申し上げますと、自分の理想に近い形の事が出来るようになりました。

以下のサイトを参考にして、ページBが追加される「要素のリサイズ」を検知し、
その度に「jquery.heightLine.js」をrefreshするという方法です。

この形なら、画像1枚のロード完了でも、高さが変化すれば検知が出来、
ローディング中でもメインコンテンツ部末尾が切れるという事はなくなりました。

まだ全ブラウザで問題が無いか、詳細検証まで出来ておりませんが、
とりあえず、Firefox(ver 46.1)、IE(11)、chrome(51)、Safari(iPhone)では
問題がありませんでした。

(参考)要素のリサイズイベントを取得
http://qiita.com/reneice/items/a5c67584a3068a75f861

今回の件で学んだことは、
JQuery.load()で読み込みを行った場合、
ロード完了イベントが用意されていないので、自前で試行錯誤する必要があり、
そこには多少の無理が発生してしまうこと。

目的、質問の背景・意図をご説明し、多角的に解決策を模索すべし

でした。

本当に皆様、ありがとうございました。
勉強になりました。

これに懲りず、今後もよろしくお願い申し上げます。

投稿2016/06/16 01:54

chibi_kuma

総合スコア85

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

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

0

質問とは関係ありませんが、jQuery3.0から、

非推奨の.load, .unload, .errorや、ajaxの.success(), .error(), .complete()が廃止

となりまして、.onを使えと言うことになりましたので、書いておきます。
ただ、こういうの色々と変更されたりするので、様子を見ながらと言う感じで。

正確には知りませんが、こうやって.onを使えというのは前から言われていたりしましたが、javascriptのモダンな書き方と言うか新しい書き方等にjQuery内部でも対応していくんだろうと思うので、古いIEのサポートも終わったことですし、わざわざ古いjQueryのバージョンでそれらに対応するよりも、環境が許す限り新しいバージョンを利用される方が良いと思います。

投稿2016/06/15 07:29

hidekichi

総合スコア366

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

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

chibi_kuma

2016/06/15 10:02

hidekichi様 コメントありがとうございました。 結構沢山の関数が廃止されてしまうのですね。 勉強になりました。 今回は、jQuery1.XXなのでまだ大丈夫ですが、 念頭には置いておくようにします。
guest

0

$(画像).bind("load",function(){...});で個別の画像の読み込み完了が取得できるのでcallback内でページBの画像全てに設定し画像数とload完了した数を比較してあげる感じになるかと思います。

イメージが読み込み完了した時点のイベントを取得 - Qiita

投稿2016/06/15 07:16

退会済みユーザー

退会済みユーザー

総合スコア0

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

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

chibi_kuma

2016/06/15 09:26

hide2e3r様 コメントありがとうございました。 添付していただいたサイトを参考にさせていただき、 コールバック関数の中に以下を実装してみました。 ---------------------------------------------- var allImage = $("img", this); //←thisを追加 var allImageCount = allImage.length; console.log("allImageCount=" + allImageCount); var completeImageCount = 0; for(var i = 0; i < allImageCount; i++){ $(allImage[i]).bind("load", function(){ completeImageCount ++; console.log("completeImageCount" + completeImageCount); if (allImageCount == completeImageCount){ console.log("画像ロード完了!" + completeImageCount); } }); } ---------------------------------------------- Firefoxで、テストしてみると、 completeImageCountのカウント値が途中で止まってしまい、 時折、「画像ロード完了!」が出ないときがあります。 うまく行く時もあるのですが…。 画像が既にキャッシュされていたりすると、 allImageCount == completeImageCountにならないのでしょうか…。 引き続き、ご教授いただけましたら、幸いです。 よろしくお願い申し上げます。
退会済みユーザー

退会済みユーザー

2016/06/15 09:45

再現性のあるコードが提示されているわけではないので検証していませんが $(window).load(function(){ //ページAの画像に対して同様の処理 }); としてみればload済みの画像に対してbindした時の動作が確認できるのではないでしょうか。 load済みの場合発火しないようであれば画像のbind以外にもタイムアウトを設定するような形で強制的に動作させるとかですかね・・・
masaya_ohashi

2016/06/15 09:46

私の追記のところにそのあたりの問題の解決法について記載しているので見てやってください。
guest

0

loadで名前がかぶって紛らわしいですが、これなら「最初に読み込まれたHTML上の画像が全て読み込み終わったあと」になります。

Javascript

1$(window).load(function(){ 2 //読み込み完了後にやりたい処理 3});

https://api.jquery.com/load-event/

#追記
ちなみにload(リソース読み込み完了時に呼ばれる方)はエレメントに対しても使えるそうなので、load(別HTMLを読み込む方)の格納先のエレメントに対してload(リソース読み込み完了時に呼ばれる方)を使えばいける気がします。ちょっと試していないのでなんとも言えませんが…

Javascript

1$("#test").load("http://example.com/test",function(){ 2 //HTMLダウンロード完了 3 $(this).load(function(){ 4 //ダウンロードしたHTML内のリソース読み込み完了時 5 }); 6});

#追記の追記
どうもloadだとうまく動かなかったので、テクニカルなことをすることにしました。
他の方の意見も踏まえ、いろいろコードを変えてあります。
jQuery.load(別HTMLを読み込む方)ではなく、jQuery.getを使う理由は、カウント処理を登録する前にHTMLに追加されてしまうとloadイベントが呼ばれるタイミングを逸してしまうからです。

Javascript

1var target = $("#test"); // 読み込んだHTMLを格納するタグ 2 3$.get("./insertPage.html", function(data){ 4 var insertHtml = $(data); // getで取ってきたHTMLをjQueryオブジェクトに変換 5 var imageCount = $("img", insertHtml).length; // insertHtml内のimgの枚数を数える 6 target.data("imageCount", imageCount); // jQuery.dataを使って保持しておく 7 8 // imgタグのloadイベント時にカウントダウンするよう登録 9 $("img", insertHtml).on("load", function(){ 10 target.data("imageCount", target.data("imageCount") - 1); // 1減らす 11 if(target.data("imageCount") == 0) { 12 // カウントが0になったとき、すべての画像が読み込み終わったことになる 13 } 14 }); 15 16 // ここで初めてtargetタグにHTMLが挿入されるので、 17 // loadイベント登録より前に画像が読み込まれることはない 18 target.append(insertHtml); 19});

補足
なお、画像が一枚もないときはカウントが0になったとき…の部分に来ないので、imageCount==0の時には別で処理を書く必要があります。

投稿2016/06/15 06:37

編集2016/06/15 09:19
masaya_ohashi

総合スコア9206

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

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

masaya_ohashi

2016/06/15 06:40 編集

っと、質問文にすでに書いてあることでしたね…よく読み解けておらず申し訳ありません。 本題は「loadで読み込んだBの画像が読み込み終わった時」のイベントが掴みたいということでしょうか?コールバックとはどのタイミングで呼ばれるものですか?
chibi_kuma

2016/06/15 08:19

masaya_ohashi様 コメントありがとうございました。 >本題は「loadで読み込んだBの画像が読み込み終わった時」のイベントが掴みたいということでしょうか? はい、その通りです。 >コールバックとはどのタイミングで呼ばれるものですか? jScrollのソースを確認したところ、.load()(別HTMLを読み込む方)の 第2引数で設定できるコールバック関数内の最後の方で、 ユーザー自作のコールバック関数が呼ばれています。 $(略).load("ページBのURL",function(){ ~略~ if (_options.callback) { _options.callback.call(this); // ←ユーザー自作のコールバック呼び出し } } ユーザー自作のコールバック関数の中で、 教えていただいた以下を試してみました。 $(this).load(function(){ console.log("ここを通過!"); }); $(this).load(function(){ の行にブレイクを仕掛けてみましたところ、 ちゃんとそこで止まるのですが、その後ステップ実行してみると、 中には入らず素通りしてしまいました。 thisは、ページBの要素がちゃんと入っていましたが…。 引き続き、ご教授くださいますよう、お願い申し上げます。
masaya_ohashi

2016/06/15 10:02

ぐわ、しまった、よく考えたらこれはjScroll内の処理でloadが使われているから根本的な解決にならないですね… 例えばですが、読み込まれる側のHTMLにscriptでカウント処理を書いて、カウントが0になった時にベース側のHTMLに定義されたメソッドを呼び出す等の処理はいかがでしょうか?
masaya_ohashi

2016/06/15 10:22

別の回答としてその例を追加しました。
guest

0

最終的な要素の高さが「全ての画像を読み込んだ時」と一致するならば、全ての画像の load イベントが発火し終えた時を狙ってみてはいかがでしょうか。
必要なら window load も検出し、どちらか遅い方を狙えばいいと思います。

HTML

1<p id="abc"></p> 2<script> 3'use stirct'; 4(function (jQuery) { 5 function handleLoad (event) { 6 var data = event.data; 7 8 console.log(event.target.src); 9 10 if (++data.i === data.length) { 11 console.log('all image loaded!'); 12 } 13 } 14 15 jQuery('#abc').load('test.txt', function () { 16 var img = jQuery('img', this); 17 18 img.on('load', {length: img.length, i: 0}, handleLoad); 19 }); 20}(jQuery)); 21</script>

Re: chibi_kuma さん

投稿2016/06/15 12:27

think49

総合スコア18164

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

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

chibi_kuma

2016/06/16 01:53

think49様 コメントありがとうございました。 「最終的な要素の高さが「全ての画像を読み込んだ時」と一致する」かどうかは 微妙なところでして…。レスポンシブになっているので、実際には、 「画像類を読み込んで、サイズや配置を計算し終わった後」じゃないとダメっぽいですね…。 補足にも書かせていただいた通り、「全ての画像がロードし終わった後」まで、 高さの修正を待ってしまうと、読み込み中はメインコンテンツ部末尾が切れたままになってしまう為、 ちょっと理想とは違う事にも気が付きました。(…気付くのが遅いよ!) 今朝、もう1つ試してみたいことがあったので、それを試してみたところ、 理想に違い形になったようなので、一旦、ここでクローズとさせていただき、 のちほど自己解決方法について記載をさせていただきます。 記載していただいたソース、見たことがない記述が満載で、ビックリしました。 勉強になります!
guest

0

###一番ベースになるページ

Javascript

1function loaded(element) { 2 console.log("image loaded"); 3 console.log(element); 4} 5$(function(){ 6 $(".scroll").jscroll(); 7});

HTML

1<div class="scroll"> 2</div>

###読み込まれていくページ

HTML

1<script> 2(function(){ 3 var target = $("#insertPage001");// このHTMLのルートタグを用意する 4 var imageCount = $("img", target).length; // このHTML内のimgの枚数を数える 5 target.data("imageCount", imageCount); 6 $("img", target).on("load", function(){ 7 target.data("imageCount", target.data("imageCount") - 1); 8 if(target.data("imageCount") == 0) { 9 // カウントが0になったとき、すべての画像が読み込み終わったことになる 10 loaded(target); 11 } 12 }); 13})(); 14</script> 15<div id="insertPage001"> 16 <img src="sample.jpg"> 17</div> 18<a href="insertPage002.html">next page</a>

読み込まれていくページに必ずルート要素エレメントに一意のIDを振っていく必要がありますが、こんなかんじでどうでしょう。

読み込まれていくページのscriptタグに直接書かれた処理は、ベースページにappendされた時点で即時実行されます。そのため、imgタグの読み込みより実行は早いです。なので、imgタグへloadイベントの紐付けが画像読み込みタイミングより早く行われます。そしてそこでカウントが終わり次第、ベースページに用意したメソッドを呼び出すようにすればベース側で処理を一本化できるかと思います。

投稿2016/06/15 10:22

masaya_ohashi

総合スコア9206

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

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

chibi_kuma

2016/06/15 10:59

masaya_ohashi様 コメントありがとうございます。 回答がちょっと追いついていなくてすいません。 >ぐわ、しまった、よく考えたらこれはjScroll内の処理でloadが使われているから根本的な解決にならないですね… そ、そうなんです…。(すいません…) jScroll内の処理を大幅に書き換えねばなりませんし、(それでもいいんですけど…) そもそも、画像のロードが全部完了するまで描画が行われなくなるような気がするので、 「遅延ローディング」実装する目的から外れてきてしまいます。 ちょっと根本から考え直すべきなのかも知れません。 そもそも何故、「画像のロード完了イベントを掴みたい」と思ったのかについて、 ご説明したほうがよいかも知れませんので、一度、質問文を編集させていただきますので、 少しお待ちいただけますでしょうか? 色々お知恵をいただき、ありがとうございます。
masaya_ohashi

2016/06/15 13:44

Bページに上記のコードを埋め込んでjquery.heightLine.jsのrefreshを呼ぶことはできない感じですか?
chibi_kuma

2016/06/16 02:08

masaya_ohashi様 コメントありがとうございました。 ページBの方は、ページAに追加される部分だけが読み込まれる仕組みになっておりまして、 スクリプトを効かせることが出来ないようです。 沢山コメントを頂き、本当にありがとうございました。 masaya_ohashi様にベストアンサーを差し上げたかったのですが、 自己解決にするとそれが出来ないようで、申し訳ありませんでした。 画像の検知を待つ方法では問題がある事に気がつけたのは、masaya_ohashi様のお陰です。 いろいろ考えていただきましたのに、このような結果になり、申し訳ありませんでした。 また、よろしくお願い申し上げます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問