Advertisement
toenailsin

DOMCompat

Jul 4th, 2011
127
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. /**
  2.  * DOM Compatibility Script
  3.  * @author : Christopher Powe
  4.  * @site : http://pastebin.com/GH6YWNzR
  5.  * @date : July 12, 2011
  6.  *
  7.  * This script has only been briefly tested and i do not guarantee that this
  8.  * script will work very well, if at all.
  9.  *
  10.  * The following stuff is added:
  11.  *
  12.  * - addEventListener
  13.  * - removeEventListener
  14.  * - event.preventDefault
  15.  * - event.stopPropagation
  16.  * - event.pageX / event.pageY
  17.  * - xmlhttprequest
  18.  * - getElementsByClassName
  19.  * - classList
  20.  * - querySelector
  21.  * - string.trim
  22.  *
  23.  * Tested in:
  24.  *
  25.  * IE 5.5, 6, 7, 8, 9
  26.  * FF 4
  27.  * OP 10.50
  28.  * CR 14
  29.  *
  30. **/
  31. (function(){
  32.     "use strict";
  33.     var stuffToAdd = [];
  34.    
  35.     // add trim method if missing
  36.     if (String.trim === undefined){
  37.         String.prototype.trim = function(){
  38.             return this.replace(/^\s+|\s+$/g, '');
  39.         }
  40.     }
  41.    
  42.     // add the w3c way to add events
  43.     if (window.addEventListener === undefined){
  44.         window.addEventListener = function(type, handler, capture){
  45.             // create an object to store all this event
  46.             var e = {};
  47.             e.type = 'on' + type;
  48.             e.element = this;
  49.             e.handler = handler;
  50.             e.capture = capture;
  51.             // in most cases, use the document object instead of the window
  52.             if (e.element === window && (
  53.                 e.type !== 'onload' &&
  54.                 e.type !== 'unload' &&
  55.                 e.type !== 'blur' &&
  56.                 e.type !== 'focus'
  57.             )){
  58.                 e.element = document;
  59.             }
  60.             // set event capture if requested
  61.             if (e.capture === true){
  62.                 e.element.setCapture();
  63.             }
  64.             // create a wrapper for the event handler
  65.             e.wrapper = function(event){
  66.                 // add some missing event properties
  67.                 event.pageX = event.clientX + document.body.scrollLeft;
  68.                 event.pageY = event.clientY + document.body.scrollTop;
  69.                 event.preventDefault = function(){
  70.                     this.returnValue = false;
  71.                 }
  72.                 event.stopPropagation = function(){
  73.                     this.cancelBubble = true;
  74.                 }
  75.                 // call the handler
  76.                 return e.handler.call(e.element, event);
  77.             };
  78.             // save to object
  79.             if (e.element.events === undefined) e.element.events = [];
  80.             e.element.events.push(e);
  81.             // attach the event
  82.             e.element.attachEvent(e.type, e.wrapper);
  83.         };
  84.         stuffToAdd.push({
  85.             name: 'addEventListener',
  86.             value: window.addEventListener
  87.         });
  88.     }
  89.    
  90.     // add the w3c way to remove events
  91.     if (window.removeEventListener === undefined){
  92.         window.removeEventListener = function(type, handler){
  93.             var e = {}, i;
  94.             e.type = 'on' + type;
  95.             e.element = this;
  96.             e.handler = handler;
  97.             // in some cases, use the document object instead of the window
  98.             if (e.element.setInterval !== undefined && (
  99.                 e.type !== 'onload' && e.type !== 'unload' && e.type !== 'blur' && e.type !== 'focus'
  100.             )){
  101.                 e.element = document;
  102.             }
  103.             // check for the event stack
  104.             if (e.element.events === undefined) return false;
  105.             // search for the wrapper associated with this handler
  106.             i = e.element.events.length;
  107.             while (i--){
  108.                 if (e.element.events[i].type !== e.type || e.element.events[i].handler !== e.handler) continue;
  109.                 e.wrapper = e.element.events[i].wrapper;
  110.                 e.element.events.splice(i, 1);
  111.                 break;
  112.             }
  113.             if (e.wrapper === undefined) return false;
  114.             e.element.detachEvent(e.type, e.wrapper);
  115.         };
  116.         stuffToAdd.push({
  117.             name: 'removeEventListener',
  118.             value: window.removeEventListener
  119.         });
  120.     }
  121.    
  122.     // get elements by class
  123.     if (document.getElementsByClassName === undefined){
  124.         document.getElementsByClassName = function(className){
  125.             var className = ' ' + className + ' ', results = [], i = document.all.length;
  126.             while (i--){
  127.                 if ((' ' + document.all[i].className + ' ').indexOf(className) !== -1){
  128.                     results.push(document.all[i]);
  129.                 }
  130.             }
  131.             return results;
  132.         };
  133.         stuffToAdd.push({
  134.             name: 'getElementsByClassName',
  135.             value: document.getElementsByClassName
  136.         });
  137.     }
  138.    
  139.     // add query selector if missing
  140.     // based off code by Paul Young
  141.     // http://ajaxian.com/archives/creating-a-queryselector-for-ie-that-runs-at-native-speed
  142.     if (document.querySelectorAll === undefined){
  143.         document.querySelectorAll = function(selector){
  144.             // result stack
  145.             document.__qsResult = [];
  146.             // create a new style element
  147.             var head = document.documentElement.firstChild;
  148.             var styleTag = document.createElement('style');
  149.             head.appendChild(styleTag);
  150.             // add expression to style element
  151.             styleTag.styleSheet.cssText = selector + '{x:expression(document.__qsResult.push(this))}';
  152.             window.scrollBy(0, 0);
  153.             head.removeChild(styleTag);
  154.             // copy the results into a new array
  155.             var result = [];
  156.             for (var i in document.__qsResult){
  157.                 result.push(document.__qsResult[i]);
  158.             }
  159.             return result;
  160.         }
  161.         document.querySelector = function(selector){
  162.             var items = document.querySelectorAll(selector);
  163.             return items.length ? items[0] : null;
  164.         }
  165.     }
  166.    
  167.     // add ajax method
  168.     if (window.XMLHttpRequest === undefined){
  169.         window.XMLHttpRequest = function(){
  170.             return new ActiveXObject("Microsoft.XMLHTTP");
  171.         };
  172.     }
  173.    
  174.     // add the classlist object if missing
  175.     // based off code by Eli Grey
  176.     // https://developer.mozilla.org/en/dom/element.classlist
  177.     if (document.createElement('br').classList === undefined){
  178.         var classList = function(element){
  179.             this.classes = String.prototype.trim.call(element.className);
  180.             this.classes = this.classes ? this.classes.split(/\s+/) : [];
  181.             this._updateClassName = function(){
  182.                 element.className = this.toString();
  183.             };
  184.         }
  185.         classList.prototype = {
  186.             item: function(i){
  187.                 return this.classes[i] || null;
  188.             },
  189.             add: function(className){
  190.                 className = className.trim();
  191.                 var i = this.classes.length;
  192.                 while (i--){
  193.                     if (this.classes[i] === className){
  194.                         return;
  195.                     }
  196.                 }
  197.                 this.classes.push(className);
  198.                 this._updateClassName();
  199.             },
  200.             remove: function(className){
  201.                 className = className.trim();
  202.                 var i = this.classes.length;
  203.                 while (i--){
  204.                     if (this.classes[i] === className){
  205.                         this.classes.splice(i, 1);
  206.                         this._updateClassName();
  207.                         return;
  208.                     }
  209.                 }
  210.             },
  211.             contains: function(className){
  212.                 className = className.trim();
  213.                 var i = this.classes.length;
  214.                 while (i--){
  215.                     if (this.classes[i] === className){
  216.                         return true;
  217.                     }
  218.                 }
  219.                 return false;
  220.             },
  221.             toggle: function(className){
  222.                 className = className.trim();
  223.                 var i = this.classes.length;
  224.                 while (i--){
  225.                     if (this.classes[i] === className){
  226.                         this.classes.splice(i, 1);
  227.                         this._updateClassName();
  228.                         return;
  229.                     }
  230.                 }
  231.                 this.classes.push(className);
  232.                 this._updateClassName();
  233.             },
  234.             toString: function(){
  235.                 return this.classes.join(' ');
  236.             }
  237.         };
  238.         stuffToAdd.push({
  239.             name: 'classList',
  240.             get: function classListGetter(){
  241.                 return new classList(this);
  242.             }
  243.         });
  244.     }
  245.    
  246.     // rename element to htmlelement
  247.     if (window.HTMLElement === undefined){
  248.         if (window.Element !== undefined){
  249.             window.HTMLElement = window.Element;
  250.         }
  251.     }
  252.    
  253.     // nothind to add
  254.     if (stuffToAdd.length === 0){
  255.         return;
  256.     }
  257.    
  258.     // use the element prototype
  259.     // check: do browsers with the HTMLElement prototype also support defineProperty?
  260.     if (window.HTMLElement !== undefined){
  261.         var i = stuffToAdd.length, propDesc = {
  262.             configurable: true,
  263.             writeable: true
  264.         };
  265.         while (i--){
  266.             if (propDesc.get !== undefined) delete propDesc.get;
  267.             if (propDesc.value !== undefined) delete propDesc.value;
  268.             if (stuffToAdd[i].get !== undefined){
  269.                 propDesc.get = stuffToAdd[i].get;
  270.                 propDesc.enumerable = false;
  271.             }
  272.             else {
  273.                 propDesc.value = stuffToAdd[i].value;
  274.                 propDesc.enumerable = true;
  275.             }
  276.             Object.defineProperty(window.HTMLElement.prototype, stuffToAdd[i].name, propDesc);
  277.         }
  278.     }
  279.    
  280.     // create a wrapper for each method
  281.     else {
  282.         var wrapMethod = function(object, methodName){
  283.             var method = object[methodName];
  284.             object[methodName] = function(){
  285.                 var result = Function.prototype.apply.call(method, object, arguments);
  286.                 if (result){
  287.                     if (result.length !== undefined){
  288.                         for (i = result.length; i--; ){
  289.                             for (item in stuffToAdd){
  290.                                 result[i][item] = stuffToAdd[item];
  291.                             }
  292.                         }
  293.                     }
  294.                     else {
  295.                         i = stuffToAdd.length;
  296.                         while (i--){
  297.                             result[stuffToAdd[i].name] = stuffToAdd[i].get !== undefined ? stuffToAdd[i].get.call(result) : stuffToAdd[i].value;
  298.                         }
  299.                     }
  300.                 }
  301.                 return result;
  302.             };
  303.         }
  304.         // methods to wrap
  305.         wrapMethod(document, 'createElement');
  306.         wrapMethod(document, 'getElementById');
  307.         wrapMethod(document, 'getElementsByTagName');
  308.         wrapMethod(document, 'getElementsByClassName');
  309.     }
  310. })();
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement