DOM-shim for all browsers including IE <8

    Good day dear harazhiteli.

    Many javascript programmers have come across some unsupported DOM JS API functions in some browsers (we will not point with a finger). Surely, many are familiar with the wonderful libraries es5-shim and DOM-shim for solving compatibility problems between different browsers, and DOM-shim also "pulls" the browser to the DOM4 level.

    In this article, I will tell you how to make DOM-shim in IE6 and IE7 in order to forget about the existence of these browsers forever.

    Problem


    There is nothing to tell. IE earlier than version 9 does not support a lot of the standard DOM API:
    • addEventListener
    • removeEventListener
    • dispachEvent
    • classList
    • etc.

    And if IE8 can be “tightened up" by implementing the necessary functionality using DOM-shim , then IE6 and IE7, unfortunately, are not supported by this library (as of 11.24.2011 issues / 29 ) due to the fact that IE <8 does not have Node. prototype.

    Decision


    Actually, the solution is quite obvious and I used it in my projects a year ago, when I just started to study javascript - behavior: url (.htc) [ Introduction to DHTML Behaviors ]. But then I had to abandon this decision, because it really, really slowed down the page loading - I had to wait 30 seconds, after the page loaded for a relatively small page.
    After some time, I accidentally stumbled upon information on how to speed up page loading with behavior using behavior every 100 times - it turns out you just need to add lightweight = true and everything will work quite quickly.
    Now to make DOM-shim for IE <8 will not be difficult, which I did.

    Let's get started


    First, we need the original es5-shim and DOM-shim , take them and redo them, fix bugs and improve the emulation of Object.defineProperty :
    <...>
    if (!object.__defineGetter__) {
      if(descriptor["ielt8"]) {
        object["get" + property] = descriptor["get"];
        object["set" + property] = descriptor["set"];
      }
    elsethrownewTypeError(ERR_ACCESSORS_NOT_SUPPORTED);
    <...>

    Instead of just throwing an exception ERR_ACCESSORS_NOT_SUPPORTED, we will check for a special flag and if it is, save the getter and setter under special names.
    Because in IE <8 there is no Node.prototype (which is passed to Object.defineProperty), create a special object into which our getters and setters will accumulate:
    var elementProto = window.HTMLElement && window.HTMLElement.prototype || 
          /*ie8*/window.Element && window.Element.prototype || 
          /*ielt8*/(window["_ielt8_Element_proto"] = {});
    

    We will transmit 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. All that remains is to “hang” it on all the elements on the page.
    Create the dom-shim.ielt8.htc file:
    <PUBLIC:COMPONENT lightWeight="true">
    <PUBLIC:PROPERTYNAME="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 that's all. Now we have Node.classList even in IE6!

    The following properties are added similarly:
    • addEventListener
    • removeEventListener
    • dispatchEvent
    • attributes (fixed)
    • children (fixed)
    • 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 attributes, for this I save the original attributes in a special container at the beginning of the htc script:
    if(!this._)this._={};
    //Save original attributes propertythis._.__ielt8_attributes__=this.attributes;
    

    So, in IE6, the implementation of behavior is different from IE7: in IE7, the original overrides in the <PUBLIC:PROPERTY NAME="attributes" GET="getAttributes" />properties are available in the script , and in IE6, they are not available - the getAttributes getter is called immediately.
    Therefore, for IE6 we make a separate file.

    2. Do not attach behavior to all elements ("*") since in IE <8, it is hung on some unsupported element and an error occurs. To fix it, you just need to specify all the html tags in style:
    <style>
    html,body,div,span,object,iframe,h1,<...все html теги...>,textarea,input,select {
     behavior: url(dom-shim.ielt8.htc)
    }
    </style>
    


    Total


    Link to the library: github.com/termi/ES5-DOM-SHIM
    I 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 last 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 to examples / microdataTemplater, open templaterTest.html)
    Offer to add what happened in DOM-shim : github.com / Raynos / DOM-shim / issues / 29

    update 11/27/2011:

    Limitations


    .htc files must be on 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 restriction significantly complicates the use of the library - you can’t just put the .htc file on a static server and forget about it. Be sure to make sure that you have all the necessary .htc files on the same domain as the site.
    Same-domain limitation
    update 12/19/2011:
    Same-domain limitation solution via nginx proxy

    Also popular now: