Detect if browser supports data uri scheme with iframes

后端 未结 2 2065
借酒劲吻你
借酒劲吻你 2020-12-19 13:17

Internet Explorer does not support the data uri scheme for iframe urls (see http://msdn.microsoft.com/en-us/library/cc848897%28v=vs.85%29.aspx). Other browsers do. As browse

相关标签:
2条回答
  • 2020-12-19 13:47

    If the onload event of the iframe with a data: URI fires, the browser supports data: URIs. Otherwise, the browser doesn't support data: URIs.

    The example code also checks if scripting is allowed from a data: URI by sending a message from the iframe to the parent window.

    Working code

    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);
        }
    };
    

    Usage

    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');
    });
    

    If you want more advanced control, you can call it like this:

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

    Demo

    Play with it on JSFiddle.

    0 讨论(0)
  • 2020-12-19 13:51

    This solution by Kevin Martin is tested and seems to be giving the correct result in IE, FF and 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=='));
    

    Unlike some of the other suggestions, it is synchronous - no need to mess around with timeouts or callbacks.

    0 讨论(0)
提交回复
热议问题