pastebin

selectivizr.js
  1. /*
  2. selectivizr v1.0.3b - (c) Keith Clark, freely distributable under the terms
  3. of the MIT license.
  4.  
  5. selectivizr.com
  6. */
  7. /*
  8.  
  9. Notes about this source
  10. -----------------------
  11.  
  12.  * The #DEBUG_START and #DEBUG_END comments are used to mark blocks of code
  13.    that will be removed prior to building a final release version (using a
  14.    pre-compression script)
  15.  
  16.  
  17. References:
  18. -----------
  19.  
  20.  * CSS Syntax          : http://www.w3.org/TR/2003/WD-css3-syntax-20030813/#style
  21.  * Selectors           : http://www.w3.org/TR/css3-selectors/#selectors
  22.  * IE Compatability    : http://msdn.microsoft.com/en-us/library/cc351024(VS.85).aspx
  23.  * W3C Selector Tests  : http://www.w3.org/Style/CSS/Test/CSS3/Selectors/current/html/tests/
  24.  
  25. */
  26.  
  27. (function(win) {
  28.  
  29.         // If browser isn't IE, then stop execution! This handles the script
  30.         // being loaded by non IE browsers because the developer didn't use
  31.         // conditional comments.
  32.         if (/*@cc_on!@*/true) return;
  33.  
  34.         // =========================== Init Objects ============================
  35.  
  36.         var doc = document;
  37.         var root = doc.documentElement;
  38.         var xhr = getXHRObject();
  39.         var ieVersion = /MSIE (\d+)/.exec(navigator.userAgent)[1];
  40.        
  41.         // If were not in standards mode, IE is too old / new or we can't create
  42.         // an XMLHttpRequest object then we should get out now.
  43.         if (doc.compatMode != 'CSS1Compat' || ieVersion<6 || ieVersion>8 || !xhr) {
  44.                 return;
  45.         }
  46.        
  47.        
  48.         // ========================= Common Objects ============================
  49.  
  50.         // Compatiable selector engines in order of CSS3 support. Note: '*' is
  51.         // a placholder for the object key name. (basically, crude compression)
  52.         var selectorEngines = {
  53.                 "NW"                                                            : "*.Dom.select",
  54.                 "MooTools"                                                      : "$$",
  55.                 "DOMAssistant"                                          : "*.$",
  56.                 "Prototype"                                                     : "$$",
  57.                 "YAHOO"                                                         : "*.util.Selector.query",
  58.                 "Sizzle"                                                        : "*",
  59.                 "jQuery"                                                        : "*",
  60.                 "dojo"                                                          : "*.query"
  61.         };
  62.  
  63.         var selectorMethod;
  64.         var enabledWatchers                                     = [];     // array of :enabled/:disabled elements to poll
  65.         var domPatches                                                  = [];
  66.         var ie6PatchID                                                  = 0;      // used to solve ie6's multiple class bug
  67.         var patchIE6MultipleClasses                             = true;   // if true adds class bloat to ie6
  68.         var namespace                                                   = "slvzr";
  69.  
  70.         // Stylesheet parsing regexp's
  71.         var RE_COMMENT                                                  = /(\/\*[^*]*\*+([^\/][^*]*\*+)*\/)\s*?/g;
  72.         var RE_IMPORT                                                   = /@import\s*(?:(?:(?:url\(\s*(['"]?)(.*)\1)\s*\))|(?:(['"])(.*)\3))\s*([^;]*);/g;
  73.         var RE_ASSET_URL                                                = /(behavior\s*?:\s*)?\burl\(\s*(["']?)(?!data:)([^"')]+)\2\s*\)/g;
  74.         var RE_PSEUDO_STRUCTURAL                                = /^:(empty|(first|last|only|nth(-last)?)-(child|of-type))$/;
  75.         var RE_PSEUDO_ELEMENTS                                  = /:(:first-(?:line|letter))/g;
  76.         var RE_SELECTOR_GROUP                                   = /((?:^|(?:\s*})+)(?:\s*@media[^{]+{)?)\s*([^\{]*?[\[:][^{]+)/g;
  77.         var RE_SELECTOR_PARSE                                   = /([ +~>])|(:[a-z-]+(?:\(.*?\)+)?)|(\[.*?\])/g;
  78.         var RE_LIBRARY_INCOMPATIBLE_PSEUDOS             = /(:not\()?:(hover|enabled|disabled|focus|checked|target|active|visited|first-line|first-letter)\)?/g;
  79.         var RE_PATCH_CLASS_NAME_REPLACE                 = /[^\w-]/g;
  80.        
  81.         // HTML UI element regexp's
  82.         var RE_INPUT_ELEMENTS                                   = /^(INPUT|SELECT|TEXTAREA|BUTTON)$/;
  83.         var RE_INPUT_CHECKABLE_TYPES                    = /^(checkbox|radio)$/;
  84.  
  85.         // Broken attribute selector implementations (IE7/8 native [^=""], [$=""] and [*=""])
  86.         var BROKEN_ATTR_IMPLEMENTATIONS                 = ieVersion>6 ? /[\$\^*]=(['"])\1/ : null;
  87.  
  88.         // Whitespace normalization regexp's
  89.         var RE_TIDY_TRAILING_WHITESPACE                 = /([(\[+~])\s+/g;
  90.         var RE_TIDY_LEADING_WHITESPACE                  = /\s+([)\]+~])/g;
  91.         var RE_TIDY_CONSECUTIVE_WHITESPACE              = /\s+/g;
  92.         var RE_TIDY_TRIM_WHITESPACE                             = /^\s*((?:[\S\s]*\S)?)\s*$/;
  93.        
  94.         // String constants
  95.         var EMPTY_STRING                                                = "";
  96.         var SPACE_STRING                                                = " ";
  97.         var PLACEHOLDER_STRING                                  = "$1";
  98.  
  99.         // =========================== Patching ================================
  100.  
  101.         // --[ patchStyleSheet() ]----------------------------------------------
  102.         // Scans the passed cssText for selectors that require emulation and
  103.         // creates one or more patches for each matched selector.
  104.         function patchStyleSheet( cssText ) {
  105.                 return cssText.replace(RE_PSEUDO_ELEMENTS, PLACEHOLDER_STRING).
  106.                         replace(RE_SELECTOR_GROUP, function(m, prefix, selectorText) { 
  107.                         var selectorGroups = selectorText.split(",");
  108.                         for (var c = 0, cs = selectorGroups.length; c < cs; c++) {
  109.                                 var selector = normalizeSelectorWhitespace(selectorGroups[c]) + SPACE_STRING;
  110.                                 var patches = [];
  111.                                 selectorGroups[c] = selector.replace(RE_SELECTOR_PARSE,
  112.                                         function(match, combinator, pseudo, attribute, index) {
  113.                                                 if (combinator) {
  114.                                                         if (patches.length>0) {
  115.                                                                 domPatches.push( { selector: selector.substring(0, index), patches: patches } )
  116.                                                                 patches = [];
  117.                                                         }
  118.                                                         return combinator;
  119.                                                 }              
  120.                                                 else {
  121.                                                         var patch = (pseudo) ? patchPseudoClass( pseudo ) : patchAttribute( attribute );
  122.                                                         if (patch) {
  123.                                                                 patches.push(patch);
  124.                                                                 return "." + patch.className;
  125.                                                         }
  126.                                                         return match;
  127.                                                 }
  128.                                         }
  129.                                 );
  130.                         }
  131.                         return prefix + selectorGroups.join(",");
  132.                 });
  133.         };
  134.  
  135.         // --[ patchAttribute() ]-----------------------------------------------
  136.         // returns a patch for an attribute selector.
  137.         function patchAttribute( attr ) {
  138.                 return (!BROKEN_ATTR_IMPLEMENTATIONS || BROKEN_ATTR_IMPLEMENTATIONS.test(attr)) ?
  139.                         { className: createClassName(attr), applyClass: true } : null;
  140.         };
  141.  
  142.         // --[ patchPseudoClass() ]---------------------------------------------
  143.         // returns a patch for a pseudo-class
  144.         function patchPseudoClass( pseudo ) {
  145.  
  146.                 var applyClass = true;
  147.                 var className = createClassName(pseudo.slice(1));
  148.                 var isNegated = pseudo.substring(0, 5) == ":not(";
  149.                 var activateEventName;
  150.                 var deactivateEventName;
  151.  
  152.                 // if negated, remove :not()
  153.                 if (isNegated) {
  154.                         pseudo = pseudo.slice(5, -1);
  155.                 }
  156.                
  157.                 // bracket contents are irrelevant - remove them
  158.                 var bracketIndex = pseudo.indexOf("(")
  159.                 if (bracketIndex > -1) {
  160.                         pseudo = pseudo.substring(0, bracketIndex);
  161.                 }              
  162.                
  163.                 // check we're still dealing with a pseudo-class
  164.                 if (pseudo.charAt(0) == ":") {
  165.                         switch (pseudo.slice(1)) {
  166.  
  167.                                 case "root":
  168.                                         applyClass = function(e) {
  169.                                                 return isNegated ? e != root : e == root;
  170.                                         }
  171.                                         break;
  172.  
  173.                                 case "target":
  174.                                         // :target is only supported in IE8
  175.                                         if (ieVersion == 8) {
  176.                                                 applyClass = function(e) {
  177.                                                         var handler = function() {
  178.                                                                 var hash = location.hash;
  179.                                                                 var hashID = hash.slice(1);
  180.                                                                 return isNegated ? (hash == EMPTY_STRING || e.id != hashID) : (hash != EMPTY_STRING && e.id == hashID);
  181.                                                         };
  182.                                                         addEvent( win, "hashchange", function() {
  183.                                                                 toggleElementClass(e, className, handler());
  184.                                                         })
  185.                                                         return handler();
  186.                                                 }
  187.                                                 break;
  188.                                         }
  189.                                         return false;
  190.                                
  191.                                 case "checked":
  192.                                         applyClass = function(e) {
  193.                                                 if (RE_INPUT_CHECKABLE_TYPES.test(e.type)) {
  194.                                                         addEvent( e, "propertychange", function() {
  195.                                                                 if (event.propertyName == "checked") {
  196.                                                                         toggleElementClass( e, className, e.checked !== isNegated );
  197.                                                                 }                                                      
  198.                                                         })
  199.                                                 }
  200.                                                 return e.checked !== isNegated;
  201.                                         }
  202.                                         break;
  203.                                        
  204.                                 case "disabled":
  205.                                         isNegated = !isNegated;
  206.  
  207.                                 case "enabled":
  208.                                         applyClass = function(e) {
  209.                                                 if (RE_INPUT_ELEMENTS.test(e.tagName)) {
  210.                                                         addEvent( e, "propertychange", function() {
  211.                                                                 if (event.propertyName == "$disabled") {
  212.                                                                         toggleElementClass( e, className, e.$disabled === isNegated );
  213.                                                                 }
  214.                                                         });
  215.                                                         enabledWatchers.push(e);
  216.                                                         e.$disabled = e.disabled;
  217.                                                         return e.disabled === isNegated;
  218.                                                 }
  219.                                                 return pseudo == ":enabled" ? isNegated : !isNegated;
  220.                                         }
  221.                                         break;
  222.                                        
  223.                                 case "focus":
  224.                                         activateEventName = "focus";
  225.                                         deactivateEventName = "blur";
  226.                                                                
  227.                                 case "hover":
  228.                                         if (!activateEventName) {
  229.                                                 activateEventName = "mouseenter";
  230.                                                 deactivateEventName = "mouseleave";
  231.                                         }
  232.                                         applyClass = function(e) {
  233.                                                 addEvent( e, isNegated ? deactivateEventName : activateEventName, function() {
  234.                                                         toggleElementClass( e, className, true );
  235.                                                 })
  236.                                                 addEvent( e, isNegated ? activateEventName : deactivateEventName, function() {
  237.                                                         toggleElementClass( e, className, false );
  238.                                                 })
  239.                                                 return isNegated;
  240.                                         }
  241.                                         break;
  242.                                        
  243.                                 // everything else
  244.                                 default:
  245.                                         // If we don't support this pseudo-class don't create
  246.                                         // a patch for it
  247.                                         if (!RE_PSEUDO_STRUCTURAL.test(pseudo)) {
  248.                                                 return false;
  249.                                         }
  250.                                         break;
  251.                         }
  252.                 }
  253.                 return { className: className, applyClass: applyClass };
  254.         };
  255.  
  256.         // --[ applyPatches() ]-------------------------------------------------
  257.         function applyPatches() {
  258.                 var elms, selectorText, patches, domSelectorText;
  259.  
  260.                 for (var c=0; c<domPatches.length; c++) {
  261.                         selectorText = domPatches[c].selector;
  262.                         patches = domPatches[c].patches;
  263.  
  264.                         // Although some selector libraries can find :checked :enabled etc.
  265.                         // we need to find all elements that could have that state because
  266.                         // it can be changed by the user.
  267.                         domSelectorText = selectorText.replace(RE_LIBRARY_INCOMPATIBLE_PSEUDOS, EMPTY_STRING);
  268.  
  269.                         // If the dom selector equates to an empty string or ends with
  270.                         // whitespace then we need to append a universal selector (*) to it.
  271.                         if (domSelectorText == EMPTY_STRING || domSelectorText.charAt(domSelectorText.length - 1) == SPACE_STRING) {
  272.                                 domSelectorText += "*";
  273.                         }
  274.  
  275.                         // Ensure we catch errors from the selector library
  276.                         try {
  277.                                 elms = selectorMethod( domSelectorText );
  278.                         } catch (ex) {
  279.                                 // #DEBUG_START
  280.                                 log( "Selector '" + selectorText + "' threw exception '" + ex + "'" );
  281.                                 // #DEBUG_END
  282.                         }
  283.  
  284.  
  285.                         if (elms) {
  286.                                 for (var d = 0, dl = elms.length; d < dl; d++) {
  287.                                         var elm = elms[d];
  288.                                         var cssClasses = elm.className;
  289.                                         for (var f = 0, fl = patches.length; f < fl; f++) {
  290.                                                 var patch = patches[f];
  291.                                                 if (!hasPatch(elm, patch)) {
  292.                                                         if (patch.applyClass && (patch.applyClass === true || patch.applyClass(elm) === true)) {
  293.                                                                 cssClasses = toggleClass(cssClasses, patch.className, true );
  294.                                                         }
  295.                                                 }
  296.                                         }
  297.                                         elm.className = cssClasses;
  298.                                 }
  299.                         }
  300.                 }
  301.         };
  302.  
  303.         // --[ hasPatch() ]-----------------------------------------------------
  304.         // checks for the exsistence of a patch on an element
  305.         function hasPatch( elm, patch ) {
  306.                 return new RegExp("(^|\\s)" + patch.className + "(\\s|$)").test(elm.className);
  307.         };
  308.        
  309.        
  310.         // =========================== Utility =================================
  311.        
  312.         function createClassName( className ) {
  313.                 return namespace + "-" + ((ieVersion == 6 && patchIE6MultipleClasses) ?
  314.                         ie6PatchID++
  315.                 :
  316.                         className.replace(RE_PATCH_CLASS_NAME_REPLACE, function(a) { return a.charCodeAt(0) }));
  317.         };
  318.  
  319.         // --[ log() ]----------------------------------------------------------
  320.         // #DEBUG_START
  321.         function log( message ) {
  322.                 if (win.console) {
  323.                         win.console.log(message);
  324.                 }
  325.         };
  326.         // #DEBUG_END
  327.  
  328.         // --[ trim() ]---------------------------------------------------------
  329.         // removes leading, trailing whitespace from a string
  330.         function trim( text ) {
  331.                 return text.replace(RE_TIDY_TRIM_WHITESPACE, PLACEHOLDER_STRING);
  332.         };
  333.  
  334.         // --[ normalizeWhitespace() ]------------------------------------------
  335.         // removes leading, trailing and consecutive whitespace from a string
  336.         function normalizeWhitespace( text ) {
  337.                 return trim(text).replace(RE_TIDY_CONSECUTIVE_WHITESPACE, SPACE_STRING);
  338.         };
  339.  
  340.         // --[ normalizeSelectorWhitespace() ]----------------------------------
  341.         // tidies whitespace around selector brackets and combinators
  342.         function normalizeSelectorWhitespace( selectorText ) {
  343.                 return normalizeWhitespace(selectorText.
  344.                         replace(RE_TIDY_TRAILING_WHITESPACE, PLACEHOLDER_STRING).
  345.                         replace(RE_TIDY_LEADING_WHITESPACE, PLACEHOLDER_STRING)
  346.                 );
  347.         };
  348.  
  349.         // --[ toggleElementClass() ]-------------------------------------------
  350.         // toggles a single className on an element
  351.         function toggleElementClass( elm, className, on ) {
  352.                 var oldClassName = elm.className;
  353.                 var newClassName = toggleClass(oldClassName, className, on);
  354.                 if (newClassName != oldClassName) {
  355.                         elm.className = newClassName;
  356.                         elm.parentNode.className += EMPTY_STRING;
  357.                 }
  358.         };
  359.  
  360.         // --[ toggleClass() ]--------------------------------------------------
  361.         // adds / removes a className from a string of classNames. Used to
  362.         // manage multiple class changes without forcing a DOM redraw
  363.         function toggleClass( classList, className, on ) {
  364.                 var re = RegExp("(^|\\s)" + className + "(\\s|$)");
  365.                 var classExists = re.test(classList);
  366.                 if (on) {
  367.                         return classExists ? classList : classList + SPACE_STRING + className;
  368.                 } else {
  369.                         return classExists ? trim(classList.replace(re, PLACEHOLDER_STRING)) : classList;
  370.                 }
  371.         };
  372.        
  373.         // --[ addEvent() ]-----------------------------------------------------
  374.         function addEvent(elm, eventName, eventHandler) {
  375.                 elm.attachEvent("on" + eventName, eventHandler);
  376.         };
  377.  
  378.         // --[ getXHRObject() ]-------------------------------------------------
  379.         function getXHRObject() {
  380.                 if (win.XMLHttpRequest) {
  381.                         return new XMLHttpRequest;
  382.                 }
  383.                 try     {
  384.                         return new ActiveXObject('Microsoft.XMLHTTP');
  385.                 } catch(e) {
  386.                         return null;
  387.                 }
  388.         };
  389.  
  390.         // --[ loadStyleSheet() ]-----------------------------------------------
  391.         function loadStyleSheet( url ) {
  392.                 xhr.open("GET", url, false);
  393.                 xhr.send();
  394.                 return (xhr.status==200) ? xhr.responseText : EMPTY_STRING;     
  395.         };
  396.        
  397.         // --[ resolveUrl() ]---------------------------------------------------
  398.         // Converts a URL fragment to a fully qualified URL using the specified
  399.         // context URL. Returns null if same-origin policy is broken
  400.         function resolveUrl( url, contextUrl, ignoreSameOriginPolicy ) {
  401.                 ignoreSameOriginPolicy = true;
  402.                 function getProtocol( url ) {
  403.                         return url.substring(0, url.indexOf("//"));
  404.                 };
  405.  
  406.                 function getProtocolAndHost( url ) {
  407.                         return url.substring(0, url.indexOf("/", 8));
  408.                 };
  409.  
  410.                 if (!contextUrl) {
  411.                         contextUrl = baseUrl;
  412.                 }
  413.  
  414.                 // protocol-relative path
  415.                 if (url.substring(0,2)=="//") {
  416.                         url = getProtocol(contextUrl) + url;
  417.                 }
  418.  
  419.                 // absolute path
  420.                 if (/^https?:\/\//i.test(url)) {
  421.                         return !ignoreSameOriginPolicy && getProtocolAndHost(contextUrl) != getProtocolAndHost(url) ? null : url ;
  422.                 }
  423.  
  424.                 // root-relative path
  425.                 if (url.charAt(0)=="/") {
  426.                         return getProtocolAndHost(contextUrl) + url;
  427.                 }
  428.  
  429.                 // relative path
  430.                 var contextUrlPath = contextUrl.split(/[?#]/)[0]; // ignore query string in the contextUrl     
  431.                 if (url.charAt(0) != "?" && contextUrlPath.charAt(contextUrlPath.length - 1) != "/") {
  432.                         contextUrlPath = contextUrlPath.substring(0, contextUrlPath.lastIndexOf("/") + 1);
  433.                 }
  434.  
  435.                 return contextUrlPath + url;
  436.         };
  437.        
  438.         // --[ parseStyleSheet() ]----------------------------------------------
  439.         // Downloads the stylesheet specified by the URL, removes it's comments
  440.         // and recursivly replaces @import rules with their contents, ultimately
  441.         // returning the full cssText.
  442.         function parseStyleSheet( url ) {
  443.                 if (url) {
  444.                         return loadStyleSheet(url).replace(RE_COMMENT, EMPTY_STRING).
  445.                         replace(RE_IMPORT, function( match, quoteChar, importUrl, quoteChar2, importUrl2, media ) {
  446.                                 var cssText = parseStyleSheet(resolveUrl(importUrl || importUrl2, url));
  447.                                 return (media) ? "@media " + media + " {" + cssText + "}" : cssText;
  448.                         }).
  449.                         replace(RE_ASSET_URL, function( match, isBehavior, quoteChar, assetUrl ) {
  450.                                 quoteChar = quoteChar || EMPTY_STRING;
  451.                                 return isBehavior ? match : " url(" + quoteChar + resolveUrl(assetUrl, url, true) + quoteChar + ") ";
  452.                         });
  453.                 }
  454.                 return EMPTY_STRING;
  455.         };
  456.  
  457.         // --[ getStyleSheets() ]-----------------------------------------------
  458.         function getStyleSheets() {
  459.                 var url, stylesheet;
  460.                 for (var c = 0; c < doc.styleSheets.length; c++) {
  461.                         stylesheet = doc.styleSheets[c];
  462.                         if (stylesheet.href != EMPTY_STRING) {
  463.                                 url = resolveUrl(stylesheet.href);
  464.                                 if (url) {
  465.                                         stylesheet.cssText = stylesheet["rawCssText"] = patchStyleSheet( parseStyleSheet( url ) );
  466.                                 }
  467.                         }
  468.                 }
  469.         };
  470.  
  471.         // --[ init() ]---------------------------------------------------------
  472.         function init() {
  473.                 applyPatches();
  474.  
  475.                 // :enabled & :disabled polling script (since we can't hook
  476.                 // onpropertychange event when an element is disabled)
  477.                 if (enabledWatchers.length > 0) {
  478.                         setInterval( function() {
  479.                                 for (var c = 0, cl = enabledWatchers.length; c < cl; c++) {
  480.                                         var e = enabledWatchers[c];
  481.                                         if (e.disabled !== e.$disabled) {
  482.                                                 if (e.disabled) {
  483.                                                         e.disabled = false;
  484.                                                         e.$disabled = true;
  485.                                                         e.disabled = true;
  486.                                                 }
  487.                                                 else {
  488.                                                         e.$disabled = e.disabled;
  489.                                                 }
  490.                                         }
  491.                                 }
  492.                         }, 250)
  493.                 }
  494.         };
  495.  
  496.         // Determine the baseUrl and download the stylesheets
  497.         var baseTags = doc.getElementsByTagName("BASE");
  498.         var baseUrl = (baseTags.length > 0) ? baseTags[0].href : doc.location.href;
  499.         getStyleSheets();
  500.  
  501.         // Bind selectivizr to the ContentLoaded event.
  502.         ContentLoaded(win, function() {
  503.                 // Determine the "best fit" selector engine
  504.                 for (var engine in selectorEngines) {
  505.                         var members, member, context = win;
  506.                         if (win[engine]) {
  507.                                 members = selectorEngines[engine].replace("*", engine).split(".");
  508.                                 while ((member = members.shift()) && (context = context[member])) {}
  509.                                 if (typeof context == "function") {
  510.                                         selectorMethod = context;
  511.                                         init();
  512.                                         return;
  513.                                 }
  514.                         }
  515.                 }
  516.         });
  517.        
  518.  
  519.        
  520.         /*!
  521.          * ContentLoaded.js by Diego Perini, modified for IE<9 only (to save space)
  522.          *
  523.          * Author: Diego Perini (diego.perini at gmail.com)
  524.          * Summary: cross-browser wrapper for DOMContentLoaded
  525.          * Updated: 20101020
  526.          * License: MIT
  527.          * Version: 1.2
  528.          *
  529.          * URL:
  530.          * http://javascript.nwbox.com/ContentLoaded/
  531.          * http://javascript.nwbox.com/ContentLoaded/MIT-LICENSE
  532.          *
  533.          */
  534.  
  535.         // @w window reference
  536.         // @f function reference
  537.         function ContentLoaded(win, fn) {
  538.  
  539.                 var done = false, top = true,
  540.                 init = function(e) {
  541.                         if (e.type == "readystatechange" && doc.readyState != "complete") return;
  542.                         (e.type == "load" ? win : doc).detachEvent("on" + e.type, init, false);
  543.                         if (!done && (done = true)) fn.call(win, e.type || e);
  544.                 },
  545.                 poll = function() {
  546.                         try { root.doScroll("left"); } catch(e) { setTimeout(poll, 50); return; }
  547.                         init('poll');
  548.                 };
  549.  
  550.                 if (doc.readyState == "complete") fn.call(win, EMPTY_STRING);
  551.                 else {
  552.                         if (doc.createEventObject && root.doScroll) {
  553.                                 try { top = !win.frameElement; } catch(e) { }
  554.                                 if (top) poll();
  555.                         }
  556.                         addEvent(doc,"readystatechange", init);
  557.                         addEvent(win,"load", init);
  558.                 }
  559.         };
  560. })(this);
Parsed in 0.095 seconds