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

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

ただいまの
回答率

90.51%

  • JavaScript

    20323questions

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

  • HTML

    11433questions

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

  • jQuery

    8130questions

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

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

解決済

回答 6

投稿 編集

  • 評価
  • クリップ 1
  • VIEW 5,989

chibi_kuma

score 37

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

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

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 6

check解決した方法

+1

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

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

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

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

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

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

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

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

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

でした。

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

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

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

+1

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

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

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

追記

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

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

追記の追記

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

var target = $("#test"); // 読み込んだHTMLを格納するタグ

$.get("./insertPage.html", function(data){
    var insertHtml = $(data); // getで取ってきたHTMLをjQueryオブジェクトに変換
    var imageCount = $("img", insertHtml).length; // insertHtml内のimgの枚数を数える
    target.data("imageCount", imageCount); // jQuery.dataを使って保持しておく

    // imgタグのloadイベント時にカウントダウンするよう登録
    $("img", insertHtml).on("load", function(){
        target.data("imageCount", target.data("imageCount") - 1); // 1減らす
        if(target.data("imageCount") == 0) {
            // カウントが0になったとき、すべての画像が読み込み終わったことになる
        }
    });

    // ここで初めてtargetタグにHTMLが挿入されるので、
    // loadイベント登録より前に画像が読み込まれることはない
    target.append(insertHtml);
});


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

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/06/15 15:39 編集

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

    キャンセル

  • 2016/06/15 17: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の要素がちゃんと入っていましたが…。

    引き続き、ご教授くださいますよう、お願い申し上げます。

    キャンセル

  • 2016/06/15 19:02

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

    キャンセル

  • 2016/06/15 19:22

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

    キャンセル

+1

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

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

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/06/15 18: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 18:45

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

    キャンセル

  • 2016/06/15 18:46

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

    キャンセル

+1

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

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

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

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

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/06/15 19:02

    hidekichi様
    コメントありがとうございました。

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

    キャンセル

0

一番ベースになるページ

function loaded(element) {
    console.log("image loaded");
    console.log(element);
}
$(function(){
    $(".scroll").jscroll();
});
<div class="scroll">
</div>

読み込まれていくページ

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


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

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

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/06/15 19:59

    masaya_ohashi様
    コメントありがとうございます。
    回答がちょっと追いついていなくてすいません。

    >ぐわ、しまった、よく考えたらこれはjScroll内の処理でloadが使われているから根本的な解決にならないですね…

    そ、そうなんです…。(すいません…)
    jScroll内の処理を大幅に書き換えねばなりませんし、(それでもいいんですけど…)
    そもそも、画像のロードが全部完了するまで描画が行われなくなるような気がするので、
    「遅延ローディング」実装する目的から外れてきてしまいます。

    ちょっと根本から考え直すべきなのかも知れません。

    そもそも何故、「画像のロード完了イベントを掴みたい」と思ったのかについて、
    ご説明したほうがよいかも知れませんので、一度、質問文を編集させていただきますので、
    少しお待ちいただけますでしょうか?

    色々お知恵をいただき、ありがとうございます。

    キャンセル

  • 2016/06/15 22:44

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

    キャンセル

  • 2016/06/16 11:08

    masaya_ohashi様
    コメントありがとうございました。

    ページBの方は、ページAに追加される部分だけが読み込まれる仕組みになっておりまして、
    スクリプトを効かせることが出来ないようです。

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

    キャンセル

0

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

<p id="abc"></p>
<script>
'use stirct';
(function (jQuery) {
  function handleLoad (event) {
    var data = event.data;

    console.log(event.target.src);

    if (++data.i === data.length) {
      console.log('all image loaded!');
    }
  }

  jQuery('#abc').load('test.txt', function () {
    var img = jQuery('img', this);

    img.on('load', {length: img.length, i: 0}, handleLoad);
  });
}(jQuery));
</script>

Re: chibi_kuma さん

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/06/16 10:53

    think49様
    コメントありがとうございました。

    「最終的な要素の高さが「全ての画像を読み込んだ時」と一致する」かどうかは
    微妙なところでして…。レスポンシブになっているので、実際には、
    「画像類を読み込んで、サイズや配置を計算し終わった後」じゃないとダメっぽいですね…。

    補足にも書かせていただいた通り、「全ての画像がロードし終わった後」まで、
    高さの修正を待ってしまうと、読み込み中はメインコンテンツ部末尾が切れたままになってしまう為、
    ちょっと理想とは違う事にも気が付きました。(…気付くのが遅いよ!)

    今朝、もう1つ試してみたいことがあったので、それを試してみたところ、
    理想に違い形になったようなので、一旦、ここでクローズとさせていただき、
    のちほど自己解決方法について記載をさせていただきます。

    記載していただいたソース、見たことがない記述が満載で、ビックリしました。
    勉強になります!

    キャンセル

同じタグがついた質問を見る

  • JavaScript

    20323questions

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

  • HTML

    11433questions

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

  • jQuery

    8130questions

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