GithubHelp home page GithubHelp logo

srcdoc-polyfill's Introduction

srcdoc polyfill Build Status

HTML5 defines a new attribute for iFrames named srcdoc. This attribute allows developers to specify an iFrame's content in-line with the iFrame itself. For instance:

<iframe srcdoc="<html><body>Hello, <b>world</b>.</body></html>"></iframe>

This feature only began to see adoption in major browsers in early 2013. Fortunately, most older browsers support similar functionality through script-targeted URLs, i.e.

<iframe src="javascript: '<html><body>Hello, <b>world</b>.</body></html>'"></iframe>

(Because of limitations on URL length, the actual mechanism that the polyfill implements not quite this direct.)

For more on srcdoc, see the WhatWG specification and this post on Bocoup.com.

Usage

By including the script at the bottom of the document <body>, any available iFrames which declare a srcdoc attribute attribute) will receive this "shimmed" behavior. (In browsers that already implement this functionality, no change will take place.)

Note on the HTML5 sandbox attribute: Because the shim operates using a script-targeted URL in legacy environments, some configurations of the sandbox attribute may interfere with its behavior. This issue will only surface in environments that implement sandbox but that do not implement srcdoc. Because of this, this polyfill's default behavior is to issue a warning for potentially-hazardous configurations but to proceed optimistically. The API supports an force option that enables modification of this behavior.

Executing

This script may be consumed as a AMD module, a CommonJS module, or standalone via direct inclusion with a <script> element.

API

The shim also defines a minimal JavaScript API:

  • srcDoc.set( iframe [, content [, options ] ] ) - sets the content of the provided iFrame element using the srcdoc attribute where available (falling back on a script-targeted URL in non-supporting browsers).
    • content (optional) - The desired content of the iFrame. If blank, the current value of the element's srcdoc attribute will be referenced for content.
    • options (optional) - An object used to specify low-level behavior. Supports a single attribute, force, for controlling behavior in the presence of the sandbox attribute (see the note in "Usage" section of this document).
      • If unspecified, a warning will be issued and the library will attempt to shim the srcdoc behavior optimistically.
      • If true, then the target iFrame's sandbox attribute will be removed prior to setting the content. Note that this
      • If false, no warning will be issued and the library will attempt to shim the srcdoc behavior optimistically.
  • srcDoc.noConflict() - Sets the value of the global srcDoc variable to its original value. Returns the srcDoc object defined by this project for re-aliasing.

Browser Support

Tested in the following browsers:

  • Microsoft Internet Explorer
    • 6, 7, 8, 9, 10, 11
  • Microsoft Edge
    • 13, 14
  • Apple Safari
    • 4, 5.0, 5.1, 6, 6.2, 7.1, 8, 9.1, 10
  • Google Chrome
    • 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24.0.1312.5 (beta), 25.0.1364.5 (dev), 55
  • Opera
    • 11.1, 11.5, 11.6, 12.10, 12.11 (beta), 42
  • Mozilla FireFox
    • 3.0, 3.6, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18 (beta), 50

The following browsers are not supported:

  • Opera 10.0

Building

The build process for this project is written with Grunt.js. Please refer to the grunt documentation for details on installing grunt.

Tests

The shim's tests are written in QUnit, and can be run by visiting the test/index.html file in the browser, or by running grunt test from the command line.

Release Notes

  • 1.0.0 (2017-01-29)
    • Warn in the presence of the sandbox attribute if its value may cause issues in environments that support it
  • 0.2.0 (2015-10-02)
    • Wrap in "UMD" pattern, enabling more natural consumption from CommonJS and AMD environments
  • 0.1.1 (2013-03-01)
    • Allow content length to exceed the limit browsers impose on URLs
  • 0.1.0 (2012-06-13)
    • Initial release

License

Copyright (c) 2012 Mike Pennisi
Licensed under the MIT license.

srcdoc-polyfill's People

Contributors

jugglinmike avatar tbranyen avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

srcdoc-polyfill's Issues

IE9 encoding issue

The following HTML code demonstrates a problem with IE9:

<html>
<head>
<meta charset="utf-8">
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<script src="jquery.js"></script>
</head>
<body>  
<script>
function setFrame() {
    alert("Setting srcDoc for testFrame");
    srcDoc.set(document.getElementById("testFrame"),
     '<html><head><meta charset=\'UTF-8\'></head><body>' + 
       String.fromCharCode(1601) + 
     '</body></html>');
}     
</script>
  <button onclick="setFrame()">Click me</button>
  Frame 1:<br>
 <iframe src="about:blank" id="testFrame">
 </iframe>
 <script src="polyfill.js"></script>
</body>
</html>

I expect to see the Arabic character "ู", but instead see mangled text output.

I can inject an alert into polyfill that shows the content it receives is proper UTF-8.

I am serving this from a basic nginx on linux.

The problem does not show up when browsing with Chrome/FF/IE10.

(I forced polyfill to use the 'legacy' path for those to be sure).

The same issue can be seen with what is effectively the result of this:

document.getElementById("testFrame").src = "javascript:{String.fromCharCode(1601);};";

For IE9, this produces the mangled text. For IE10, it is fine.

The UTF-8 bytes in the content present when I use "view source" on the iFrame appear to be 0x0041 0x0006 in Hex, which in fact is the reverse (and padded) value of the actual desired UTF8 of 0x06 0x41.

I can also inject HTML escaped items in Hex, ie: &#x0641. This works for IE9. But using the actual UTF-8 byte sequence, which is the case in many input files, does not. Therefore, a general solution may need to escape all multibyte input characters.

Edge 17

It seems that the polyfill is broken on Edge 17.
Here is my workaround. I was to lazy to fork and create a PR.

/**
 * just a Promise wrapper around addEventListener
 * @param {HTMLElement} emitter
 * @param {String} eventName
 * @return {Promise}
 */
function fromEvent(emitter, eventName){
  return new Promise(...)
}
/**
 * @param {HTMLIFrameElement} iframe
 * @param {String} html
 * @return {Promise}
 */
function setSrcdocForIframeWithHtml(iframe, html)
{
	iframe.setAttribute("srcdoc", html);

	if (isCompliant)
	{
		return fromEvent(iframe, 'load');
	}
	
	// In Edge 17 all of that does not work, though Edge 18 will probably support srcdoc
	const
		isBadEdge = /Edge\/17\.\d+/.test(navigator.userAgent);
	
	if (!isBadEdge)
	{
		var jsUrl = "javascript: window.frameElement.getAttribute('srcdoc');";
		iframe.setAttribute("src", jsUrl);
		// Explicitly set the iFrame's window.location for
		// compatibility with IE9, which does not react to changes in
		// the `src` attribute when it is a `javascript:` URL, for
		// some reason
		if (iframe.contentWindow)
		{
			iframe.contentWindow.location = jsUrl;
		}
		return fromEvent(iframe, 'load');
	}
	return fromEvent(iframe, 'load')
	.then(function onIframeFirstLoaded()
	{
		iframe.contentWindow._my_app_getSource = function() { return html; };
		iframe.contentWindow.location = "javascript: _my_app_getSource()";
		return fromEvent(iframe, 'load');
	});
});

Support ios line browser

srcdoc-polyfill cannot support ios line browser now.

Does have any plan to support it or I could provide a pull request if you want me do.

Angular Support

I am assuming this will not support angular or any other framework that would be dynamically generating HTML with iFrames as this assumes the iFrames to be present on instantiation.

Document incompatability with "sandbox"

This polyfill's fundamental mechanism is incompatible with the "sandbox" iframe attribute. Document this, and consider issuing an explicit warning describing the problem when it occurs.

doesn't work with IE11

included the polyfill js via <script> before </body>

<iframe srcdoc="This is a test">``</iframe>

Not showing anything

most recent IE11 version: 11.0.9600

possible to use Object.defineProperty to create a srcdoc setter?

Is there any way to create a srcdoc setter on the iframe prototype? So something like the following could be supported in IE

var iframe = document.createElement("iframe");
iframe.srcdoc = "<html><body>foo</body></html>"

instead of

var iframe = document.createElement("iframe");
srcDoc.set(iframe, "<html><body>foo</body></html>");

I couldn't figure it out but I have never attempted something like this before.

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty

Content lenght limited to 4080 chars in Internet Explorer

I'm getting "SCRIPT1015: Unterminated string constant" error when trying to process srcdoc longer than 4080 characters using Internet Explorer 9.

It seems that src/location in Internet Explorer is limited to 4094 characters (including the javascript: protocol).
Do you know any workaround for this issue?

Make srcdoc-polyfill work with AngularJS

I have a mean-stack website. I want to dynamically construct a variable that contains a valid html string, then render it in an iframe. After some research, I tried the following code: (JSBin)

    <html>
        <head>
            <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.7/angular.min.js"></script>
            <script src="https://cdn.rawgit.com/jugglinmike/srcdoc-polyfill/master/srcdoc-polyfill.min.js"></script>
        </head>
        <body ng-app="app" ng-controller="Ctrl">
            <iframe srcdoc="{{content | toTrusted}}"></iframe>
            <script>
                var app = angular.module('app', []);
                app.controller("Ctrl", ["$scope", function($scope) {
                    $scope.content = "<b>hello</b>";
                }])
                app.filter('toTrusted', ['$sce', function($sce) {
                    return function(text) {
                        return $sce.trustAsHtml(text);
                    };
                }]);
            </script>
        </body>
    </html>

It works fine in Chrome, whereas it does not work in IE (eg, IE 11), even though I use src-polyfill.

Does anyone have a solution?

How to make it work in sandbox environment without allow-same-origin

Hi @jugglinmike
I used the polyfill to create custom VSTS task extension for TFS 2018 (which runs on the local server). The task also has one project which runs as build enhancer; it creates an iframe without allow-same-origin. I couldn't use the src tag because of limitation in the file being fetched as 'application/octet' type and downloaded instead of being loaded in the iframe.
Please guide me on how to ensure that srcdoc works in such a restricted environment.
Best Regards

Microsoft Edge iframe-in-iframe "Access Denied"

Kind of hard to make a good testcase for this one, because it seems a bit random when it occurs, but anyhow:

My company makes games for the internet, which in turn are included in different web pages, sometimes iframes, sometimes not, sometimes dynamically created, sometimes loaded via an URL, you get the picture.

Sometimes, not always, dynamically created iframes lose the document.domain inheritance on Edge. When this happens, window.frameElement.getAttribute('srcdoc'); gives SCRIPT5: Access Denied.

In the end I solved it by implementing the srcdoc functionality like this instead:

iframe.contentWindow.srcdoc = content;
iframe.src = 'javascript:window["srcdoc"]';

I have no idea why this is allowed and not window.frameElement but there you are.

I thought I'd open this issue (and I could provide a pull request if you want me to) in case you want to cover this edge-case as well. It's possibly rare, but real. It still works on all modern browsers AFAICT

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.