Good time dear habrazhiteli.
Many javascript programmers have come across the lack of support for some of the DOM JS API functions in some browsers (we will not point the finger). Surely, many are familiar with the wonderful
es5-shim and
DOM-shim libraries to solve compatibility problems between different browsers, and
DOM-shim also “pulls up” the browser to the level of DOM4.
In this article, I will explain how to make DOM-shim in IE6 and IE7 in order to forget forever about the existence of these browsers.
Problemma
There is nothing to tell here. IE earlier version 9 does not support a lot of the standard DOM API:
- addEventListener
- removeEventListener
- dispachEvent
- classList
- etc.
And if IE8 can be “pulled up” by implementing the necessary functionality using
DOM-shim , then IE6 and IE7, unfortunately, are not supported by this library (as of November 24,
2011 issues / 29 ) due to the fact that there is no Node in IE <8. prototype.
')
Decision
Actually, the solution is quite obvious and I used it in my projects a year ago, when I just started learning javascript - behavior: url (.htc) [
Introduction to DHTML Behaviors ]. But then I had to abandon this solution, because it really slowed down the page loading - it took 30 seconds to wait, after the page had loaded for a relatively small page.
After some time, I accidentally stumbled across information on how to speed up every 100 pages loading using behavior - it turns out you just need to add
lightweight = true and everything will work fast enough.
Now it’s easy to do DOM-shim for IE <8, which I did.
Let's get started
First we need the original
es5-shim and
DOM-shim , take them and rework them,
fix the bugs and improve the
Object.defineProperty emulation:
<...> if (!object.__defineGetter__) { if(descriptor["ielt8"]) { object["get" + property] = descriptor["get"]; object["set" + property] = descriptor["set"]; } else throw new TypeError(ERR_ACCESSORS_NOT_SUPPORTED); <...>
Instead of simply throwing out the exception
ERR_ACCESSORS_NOT_SUPPORTED, we check for the presence of a special flag and, if there is one, save the getter and setter under special names.
Because in IE <8 there is no Node.prototype (which is passed to Object.defineProperty), we will create a special object into which our getters and setters will accumulate:
var elementProto = window.HTMLElement && window.HTMLElement.prototype || window.Element && window.Element.prototype || (window["_ielt8_Element_proto"] = {});
We will pass it as usual, just add the "ielt8" flag to the
description :
Object.defineProperty(elementProto, "classList", {"get" : ..., "ielt8" : true}
Now we collect all the getters of our shim library into one object. It remains only to "hang" it on all the elements on the page.
Create a dom-shim.ielt8.htc file:
<PUBLIC:COMPONENT lightWeight="true"> <PUBLIC:PROPERTY NAME="classList" GET="getClassList" /> <SCRIPT> getClassList = window._ielt8_Element_proto.getclassList </SCRIPT> </PUBLIC:COMPONENT>
and add it to all the elements on the page:
* { behavior: url(dom-shim.ielt8.htc) }
And actually everything. Now we have a Node.classList even in IE6!
The following properties are added in the same way:
- addEventListener
- removeEventListener
- dispatchEvent
- attributes (corrected)
- children (corrected)
- firstElementChild
- lastElementChild
- nextElementSibling
- previousElementSibling
- childElementCount
- querySelectorAll
- querySelector
- insertAfter (non-standard)
- getElementsByClassName
- compareDocumentPosition
- DOCUMENT_POSITION_DISCONNECTED
- DOCUMENT_POSITION_PRECEDING
- DOCUMENT_POSITION_FOLLOWING
- DOCUMENT_POSITION_CONTAINS
- DOCUMENT_POSITION_CONTAINED_BY
Little things
1. I correct the attributes, for this purpose I save the original attributes in a special container at the beginning of the htc script:
if(!this._)this._={};
So, in IE6, the implementation of behavior differs from IE7: in IE7, original overriding
<PUBLIC:PROPERTY NAME="attributes" GET="getAttributes" />
properties are available in IE7, and in IE6 are not available — getAttributes getter is called immediately.
Therefore, for IE6 we make a separate file.
2. You can not hang the behavior on all elements ("*") because in IE <8, it is hung on some unsupported element and an error occurs. To fix it, you just need to specify all html tags in style:
<style> html,body,div,span,object,iframe,h1,<... html ...>,textarea,input,select { behavior: url(dom-shim.ielt8.htc) } </style>
Total
Library link:
github.com/termi/ES5-DOM-SHIMI want to note that my library for DOM-shim is very different from
DOM-shim due to the fact that I have been developing it for the past 8 months without knowing anything about
DOM-shim (and even about github :))
A working example can be downloaded here:
github.com/termi/Microdata-JS (download, go in examples / microdataTemplater, open templaterTest.html)
Offer to add what happened in
DOM-shim :
github.com/Raynos/DOM-shim/issues/29update 11/27/2011:
Restrictions
.htc files must be in the same domain as the .html file. For example, for the example.org/index.html file, the .htc file should be on example.org, and for the test.example.org/index.html file on test.example.org. This limitation greatly complicates the use of the library - you can not just put the .htc file on the static server and forget about it. It is necessary to make sure that all the necessary .htc files are available on the same domain as the site.
Same-domain limitationupdate 12/19/2011:
Same-domain limitation solution via nginx proxy