web-dev-qa-db-ja.com

iframeがChrome

ファイルがサーバー側で動的に生成されている間に、クライアントに「マスク」を表示しようとしています。これの推奨される回避策のように思えます(ajaxではないため)iframeを使用し、onloadまたはdoneイベントからリッスンして、ファイルが実際にサーバーからクライアントに出荷されたことを判断します。

ここに私のangularコード:

    var url = // url to my api
    var e = angular.element("<iframe style='display:none' src=" + url + "></iframe>");
    e.load(function() {
        $scope.$apply(function() {
            $scope.exporting = false;  // this will remove the mask/spinner
        });
    });
    angular.element('body').append(e);

これはFirefoxではうまく機能しますが、Chromeではうまくいきません。また、onload関数を使用しようとしました:

e.onload = function()  { //unmask here }

しかし、私もそこに運がなかった。

アイデア?

28

残念ながら、Chromeコンテンツが添付ファイルの場合、iframeのonloadイベントを使用することはできません。この answer は、どのようにそれを回避できるか。

21
rtcherry

私はこれが嫌いですが、それがまだロードされているかどうかをチェックする以外の方法を見つけることができませんでした。

var timer = setInterval(function () {
    iframe = document.getElementById('iframedownload');
    var iframeDoc = iframe.contentDocument || iframe.contentWindow.document;
    // Check if loading is complete
    if (iframeDoc.readyState == 'complete' || iframeDoc.readyState == 'interactive') {
        loadingOff();
        clearInterval(timer);
        return;
    }
}, 4000);
11
Negarrak

別の方法でそれを行うことができます:

メインドキュメント内:

function iframeLoaded() {
     $scope.$apply(function() {
            $scope.exporting = false;  // this will remove the mask/spinner
        });
}

var url = // url to my api
var e = angular.element("<iframe style='display:none' src=" + url + "></iframe>");
angular.element('body').append(e);

iframeドキュメント内(これは、urlによって参照されるページのhtml内)

    window.onload = function() {
        parent.iframeLoaded();
    }

これは、メインページとiframe内のページが同じドメインにある場合に機能します。

実際には、次の方法で親にアクセスできます。

window.parent
parent
//and, if the parent is the top-level document, and not inside another frame
top          
window.top

変数parenttopは上書きされる可能性があるため(通常は意図されていない)、window.parentを使用する方が安全です。

4
Carlos Robles

次の2点を考慮する必要があります。

1-まず、URLのドメイン名が異なる場合、他のドメインにアクセスしてAccess-Control-Allow-Origin: *ヘッダーを追加する場合を除き、これを行うことはできません。これを修正するには、これに移動します link

2-ただし、同じドメインを持っている場合、またはドメインのヘッダーにAccess-Control-Allow-Origin: *を追加した場合は、次のようにすることができます。

var url = // url to my api
var e = angular.element("<iframe style='display:none' src=" + url + "></iframe>");
angular.element(document.body).append(e);
e[0].contentWindow.onload = function() {
    $scope.$apply(function() {
        $scope.exporting = false;  // this will remove the mask/spinner
    });
};

これをあらゆる種類のブラウザーで実行しました。

0
Mehran Hatami

Chromeはメインページのロードイベントを常に発生させるわけではないので、iframeでも基本的に同じ方法で処理されるため、これが影響する可能性があることに気付きました。

開発ツールまたはパフォーマンスAPIを使用して、ロードイベントが発生しているかどうかを確認します。

http://ee.co.uk/ をチェックしたところ、コンソールを開いてwindow.performance.timingと入力すると、domComplete、loadEventStart、およびloadEventEndのエントリが0であることがわかります-少なくともこの時点で:)

Chrome hereに問題があるようです-最新バージョン31.0.1650.63を使用して2台のPCで確認しました。

更新:eeを再度チェックし、以降のリロードではなくロードイベントが発生したため、これは断続的であり、サイトでのロードエラーに関連している可能性があります。ただし、loadイベントは何でも起動する必要があります。

私自身のサイト監視が時々失敗することに気付いたので、この問題は最終日に5または6サイトで発生しました。これの原因を特定しただけです。美人の睡眠が必要なので、目が覚めたらさらに調査します。

0
Geezer68