2012-08-13 17 views
15

(先制攻撃:これを重複としてマークしたい場合は、「なぜこのエラーが発生するのですか?このエラーが発生しましたJavaScriptコードのエラーをどのように検出できるのかを知りたいのですが、Firebugコンソールにしか表示されず、画像がロードされたときにユーザーには明らかです)Firefoxで「画像が壊れているか切り詰められていますか」を検出します

I応答性の高い画像にはpicturefillを使用しています。私は画像上のloadイベントのために起動されるコールバックを持っています。したがって、誰かがブラウザウィンドウのサイズを変更するたびにコールバックが実行され、異なる画像がpicturefillによって読み込まれるようになります。

コールバックの中で、イメージデータをキャンバス経由でdataURLに変換しています。ローカルデータをlocalStorageにキャッシュして、オフラインでも利用できるようにします。

「オフライン」に関する部分に注意してください。そのため、私はブラウザのキャッシュに頼ることができません。イメージが応答性があるため、HTML5オフラインアプリケーションキャッシュが私のニーズを満たしていません。

MacのFirefox 14.0.1では、ブラウザのサイズを本当に大きかったサイズに変更してからサイズを変更すると、読み込みイメージが表示されます(これは、応答イメージとHTMLオフラインアプリケーションキャッシュとの非互換性の説明を参照してください)。大きなイメージが完全に読み込まれる前にもう一度小さなものに戻ってください。 Firebugコンソールで "Image corrupt or truncated"と報告されますが、例外はスローされず、エラーイベントも発生しません。コードに何も間違っていることは示されません。 Firebugコンソールで一方、切り捨てられたイメージはlocalStorageに格納されます。

JavaScriptでこの問題を確実かつ効率的に検出して、その画像をキャッシュしないようにするにはどうすればよいですか?

はここpicturefillによって挿入されているのimgタグを見つける方法Iループpicturefillのdivを経由だ:ここ

var cacheImage = function() { 
    var canvas, 
     ctx, 
     imageSrc; 

    imageSrc = this.getAttribute("src"); 

    if ((pf_index.hasOwnProperty('pf_s_' + imageSrc)) || 
     (imageSrc.substr(0,5) === "data:") || 
     (imageSrc === null) || (imageSrc.length === 0)) { 
      return; 
    } 

    canvas = w.document.createElement("canvas"); 
    canvas.width = this.width; 
    canvas.height = this.height; 

    ctx = canvas.getContext("2d"); 
    ctx.drawImage(this, 0, 0); 
    try { 
     dataUri = canvas.toDataURL(); 
    } catch (e) { 
     // TODO: Improve error handling here. For now, if canvas.toDataURL() 
     // throws an exception, don't cache the image and move on. 
     return; 
    } 

    // Do not cache if the resulting cache item will take more than 128Kb. 
    if (dataUri.length > 131072) { 
     return; 
    } 

    pf_index["pf_s_"+imageSrc] = 1; 

    try { 
     localStorage.setItem("pf_s_"+imageSrc, dataUri); 
     localStorage.setItem("pf_index", JSON.stringify(pf_index)); 
    } catch (e) { 
     // Caching failed. Remove item from index object so next cached item 
     // doesn't wrongly indicate this item was successfully cached. 
     delete pf_index["pf_s_"+imageSrc]; 
    } 
}; 

最後に、:

var errorLogger = function() { 
     window.console.log('Error loading image.'); 
     this.removeEventListener('load', cacheImage, false); 
    }; 

    for(var i = 0, il = ps.length; i < il; i++){ 
     if(ps[ i ].getAttribute("data-picture") !== null){ 

      image = ps[ i ].getElementsByTagName("img")[0]; 
      if (image) { 
       if ((imageSrc = image.getAttribute("src")) !== null) { 
        if (imageSrc.substr(0,5) !== "data:") { 
         image.addEventListener("load", cacheImage, false); 
         image.addEventListener('error', errorLogger, false); 
        } 
       } 
      } 
     } 
    } 

そして、ここではcacheImage()コールバックは次のようになります。私がFirebugで見ているURLのフルテキストです。

破損または切り捨て

画像:http://www.example.com/pf/external/imgs/extralarge.png

+2

''要素で 'error'イベントが発生しませんか? – MaxArt

+2

なぜ、ブラウザのキャッシュに自分の仕事をさせるのではなく、自分のイメージキャッシュをローカルストレージに実装しようとしているのだろうか? – jfriend00

+0

@ jfriend00オフラインで使用するためにイメージをキャッシュします。私はこの質問に答えましたが、私はそれを脇見のように表現しました。私はオフラインビットにもっと重点を置くように質問を編集しました。とにかく、次に明らかになるのは、HTML5のオフラインappcachingを使用しない理由です。応答イメージとHTML5オフラインアプリケーションキャッシングが互換性がない理由については、http://www.alistapart.com/articles/application-cache-is-a-douchebag/ – Trott

答えて

9

imgタグのsrc属性を変更する場合、Firefoxはloadイベントが発生していることが表示されます。これはHTML5仕様に反しています。saysは、src属性が変更された場合、既に進行中の他のフェッチを終了する必要があります(Firefoxが実行する)。イベントは送信されません。 loadイベントは、フェッチが正常に完了した場合にのみ送信する必要があります。だから、あなたがloadイベントを受け取ったという事実は、Firefoxのバグです。

ただし、画像それが完全に利用可能であるかどうか、あなたはcomplete属性を使用しようとすることができます知っている必要があります:それはないですので、

if (this.complete === false) { 
    return; 
} 

は残念ながら、Firefoxは、代わりにtruethis.completeセットを持っていますオプションもあります。

src属性を変更するたびに、新しい<img>要素を作成することをお勧めします。

+0

残念ながら、this.completeもその時にも当てはまりますので、問題を回避することはできません。本当に、Firefoxはsrcが変更されてもfalseに設定されません。Harrumph。HTML5仕様に言及してくれてありがとうございます。私はそれをチェックしなければなりません。バグ! – Trott

+0

確かに、私は今自分で試してみましたが、 'complete'フラグは' true'のままです。読み込み専用なので、手動で元に戻すことはできませんので、Firefoxがこのバグを修正するのを待つか、 –

+0

実際には、この例を試している間、私は 'src'を変更するときに' load'イベントを受け取っていないことに気付きました。そして、 'src'を変更するたびに新しい' img'要素が追加されました。イメージが完全にロードされていませんLinuxでFF 14.0.1でpngとjpgイメージを使用してテストされました[this jsfiddl e](http://jsfiddle.net/GfKCf/5/)を試してFirebugを起動し、どのイベントがコンソールに記録されているかを見てください。 –

2

私は今日この問題で自分自身を唖然としていました。エラーはFirefoxエラーコンソールに表示され続けていた点を除いて、すべて正常に動作していました(画像は予期したとおりに視覚的にロードされました)。

私の場合、完全なjqueryハンドラのinnerHtmlを使って画像をdivに差し込んでいました。 jquery呼び出しを先取りしてエラーを停止しました。

var image_holder = new Image(); 
image_holder.src = img_path;//path of image that's going to be plugged in 

私にとってはうまくいったが、それでも意味をなさない。このコードは、実際にページにプラグインするコードに到達する前に、このコードがロードするイメージを開始するので、タイミングと関係があると思います。

+0

これも私のために修正されました。奇妙な! –

関連する問題