Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

document.createElement() shim creates elements with non-null siblings in IE < 9 #64

Open
timdown opened this issue May 17, 2012 · 10 comments

Comments

@timdown
Copy link

timdown commented May 17, 2012

Example code (run in IE < 9):

var div1 = document.createElement("div");
var div2 = document.createElement("div");
alert(div2.previousSibling); // Should be null, is actually a reference to div1

nextSibling and previousSibling (and possibly other properties) should be null for a newly created element, which should effectively live in its own little vacuum until being attached to the document. I would suggest doing a thorough review of the document.createElement() shim to ensure this is the case.

This bug prevents my Rangy library working properly in IE < 9 when Modernizr is also present and is not easily worked around within Rangy code. Actually, it wouldn't be that hard to work around but I'd rather not have to, since the presence of other libraries in the page really shouldn't break the environment.

@aFarkas
Copy link
Owner

aFarkas commented May 21, 2012

@timdown

This is really bad and we can not fix it. To get html5 elements dynamically created using innerHTML. The element has to be inside of a shived document or a shived documentFragment. We are using a documentFragment and this means, that newly created elements are not disconnected anymore. The parentNode property is always and the previousSibling/nextSibling properties are sometimes busted.

The best way for you to fix this, is to use a helper function, to create save disconnected elements:

function createUnshivedElement(name){
    var isShiv;
    var ret;
    if(window.html5){
        isShiv = html5.shivMethods;
        html5.shivMethods = false;
    }
    ret = document.createElement(name);
    if(window.html5){
        html5.shivMethods = isShiv;
    }
    return ret;
}

This answer isn't really satisfying, but we don't have any other possibility.

@timdown
Copy link
Author

timdown commented May 21, 2012

I would argue that not breaking working browser methods is more important than fudging support for HTML5 features in browsers that predate the existence of HTML5, but I guess it's impossible for this library to change now.

@Raynos
Copy link

Raynos commented May 21, 2012

I didn't realize html5 shiv would do something so horrible :\ A newly created element should be a newly created element as intended.

Why does html5shiv even need to do this? I thought calling createElement("HTML5TagName") as sufficient to fix legacy browsers.

This bug should be removed.

@aFarkas
Copy link
Owner

aFarkas commented May 21, 2012

@Raynos

It's all about innerHTML:

var elem = document.createElement('div');
elem.innerHTML = '<section>dsa</section>';
document.body.appendChild(elem);

Currently this is the only known way to fix this. (+ Object.defineProperty only for IE8). Therefore we had a lot of discussion, wether the shiveMethods thing (duck punching createElement) should be opt-out or opt-in. Currently we have an opt-out solution.

@timdown
Copy link
Author

timdown commented May 28, 2012

The more I think about this, the more I dislike it. HTML5 Shiv's presence in a page by default clobbers the environment. createElement() is absolutely fundamental and works perfectly well in older IE (some quirks aside) so it's rather offensive to break it for other scripts running in the page. In my view, it's worse than Object.prototype nadgery that Prototype was vilified for.

I think fixing this bug should be the number one priority for HTML5 Shiv. No hacked-in pseudo-support for HTML5 in browsers that pre-date HTML5's existence is worth it in my view.

Sorry if the tone of this seems harsh. I feel quite strongly that this bug should be fixed.

@aFarkas
Copy link
Owner

aFarkas commented May 29, 2012

@timdown

I really understand you. Our discussion, to use an opt-out, instead of an opt-in.

Beside those things, you really should use the createUnshivedElement function. Even if we use an opt-in, your script will break as soon as people are using this configuration.

@Raynos
Copy link

Raynos commented May 29, 2012

@timdown alternatively just tell anyone who complains your code doesn't work with html5shiv that they should stop using html5shiv. A la crockford

@timdown
Copy link
Author

timdown commented Jun 3, 2012

@Raynos: I caved and added a workaround. Crockford's profile is such that he can afford to be belligerent. Mine isn't.

@andrewnicols
Copy link

Just wondering whether the following change would be suitable: andrewnicols@fix_64

I'm not sure whether the act of cloning the Node will removing the HTML5isation or not. I hit this issue with the stable version of Rangy which does not (yet) include @timdown's fix. This issue should really be fixed in HTML5shiv rather than other projects.

andrewnicols added a commit to andrewnicols/moodle that referenced this issue Apr 16, 2014
This is a backport of the Rangy workaround for a bug in HTML5Shiv, which
breaks document.createElement by returning nodes which have parent nodes.

HTML5Shiv refuses to fix this bug so Rangy has had to work around it.

For more information see:
* https://code.google.com/p/rangy/issues/detail?id=104; and
* aFarkas/html5shiv#64.
@aFarkas
Copy link
Owner

aFarkas commented Apr 16, 2014

@andrewnicols
Thanks, I will look into this tomorrow.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants