5

Internet Explorer は、iframe URL のデータ URI スキームをサポートしていません ( http://msdn.microsoft.com/en-us/library/cc848897%28v=vs.85%29.aspxを参照)。他のブラウザはそうです。ブラウザー検出にはテストと将来の保証の問題が山積しているため、機能検出を使用してこの問題を回避したいと考えています。

では、ブラウザが iframe のデータ URI スキームをサポートしているかどうかをどのように検出できますか?

4

2 に答える 2

10

Kevin Martin によるこのソリューションはテスト済みで、IE、FF、および Chrome で正しい結果が得られているようです。

function iframeDataURITest(src) {
    var support,
        iframe = document.createElement('iframe');

    iframe.style.display = 'none';
    iframe.setAttribute('src', src);

    document.body.appendChild(iframe);

    try {
        support = !!iframe.contentDocument;
    } catch (e) {
        support = false;
    }

    document.body.removeChild(iframe);

    return support;
}

console.log('Empty data uri', iframeDataURITest('data:;base64,'));
console.log('"*" data uri', iframeDataURITest('data:text/html;base64,Kg=='));

他のいくつかの提案とは異なり、これは同期的です。タイムアウトやコールバックをいじる必要はありません。

于 2015-07-08T10:18:02.250 に答える
1

with a URIのonloadイベントが発生した場合、ブラウザはURI をサポートしています。それ以外の場合、ブラウザはURIをサポートしていません。iframedata:data:data:

このコード例では、から親ウィンドウにdata:メッセージを送信することにより、URIからのスクリプト作成が許可されているかどうかもチェックします。iframe

作業コード

var iframeDataURISupport = { checked: false, supported: false, scriptingSupported: false };

function iframesSupportDataURIs(callback) {
    if (!iframeDataURISupport.checked) {
        var iframe = document.createElement('iframe'), alreadyCalled = false, done = function () {
            if (!alreadyCalled) {
                alreadyCalled = true;

                document.body.removeChild(iframe);

                console.log(iframeDataURISupport);

                callback && callback(iframeDataURISupport);
            }
        }, previousMessageHandler = window.onmessage, dataURI = 'data:text/html,<' + 'script>window.parent.postMessage("data: URIs supported", "*");<' + '/script>';

        window.onmessage = function (e) {
            if (e.data === 'data: URIs supported') {
                window.onmessage = previousMessageHandler;

                iframeDataURISupport.supported = true;
                iframeDataURISupport.scriptingSupported = true;

                done();
            } else {
                window.onmessage.apply(this, arguments);
            }
        };

        iframe.src = dataURI;
        iframe.setAttribute('style', 'display: inline-block; width: 0; height: 0; overflow: hidden; border: 0 none; padding: 0; margin: 0;'.replace(/;/g, ' !important;'));

        iframe.onload = function (e) {
            if (iframe.src === dataURI) {
                iframeDataURISupport.supported = true;

                setTimeout(done, 100);
            } else done();
        };

        document.body.appendChild(iframe);

        setTimeout(done, 500);
    } else {
        setTimeout(function () {
            callback && callback(iframeDataURISupport);
        }, 5);
    }
};

使用法

iframesSupportDataURIs(function (details) {
    alert('This browser ' + (details.supported ? 'supports' : 'does not support') + ' data: URIs. It ' + (details.scriptingSupported ? 'also supports' : 'does not support') + ' scripting from data: URIs');
});

より高度な制御が必要な場合は、次のように呼び出すことができます。

iframeDataURISupport.checked ? functionName(iframeDataURISupport) : iframesSupportDataURIs(functionName);

デモ

JSFiddleで遊んでください。

于 2014-08-04T16:31:10.707 に答える