2 IE7/IE8/IE9.js - copyright 2004-2010, Dean Edwards
3 http://code.google.com/p/ie7-js/
4 http://www.opensource.org/licenses/mit-license.php
7 /* W3C compliance for Microsoft Internet Explorer */
10 Shaggy, Martijn Wargers, Jimmy Cerra, Mark D Anderson,
11 Lars Dieckow, Erik Arvidsson, Gellért Gyuris, James Denny,
12 Unknown W Brackets, Benjamin Westfarer, Rob Eberhardt,
13 Bill Edney, Kevin Newman, James Crompton, Matthew Mastracci,
14 Doug Wright, Richard York, Kenneth Kolano, MegaZone,
15 Thomas Verelst, Mark 'Tarquin' Wilton-Jones, Rainer Åhlfors,
16 David Zulaica, Ken Kolano, Kevin Newman, Sjoerd Visscher,
20 // timestamp: Sun, 07 Mar 2010 18:13:50
22 (function(window
, document
) {
24 var IE7
= window
.IE7
= {
25 version
: "2.1(beta3)",
29 var appVersion
= IE7
.appVersion
= navigator
.appVersion
.match(/MSIE (\d\.\d)/)[1] - 0;
31 if (/ie7_off/.test(top
.location
.search
) || appVersion
< 5.5 || appVersion
>= IE7
.compat
) return;
33 var MSIE5
= appVersion
< 6;
36 var documentElement
= document
.documentElement
, body
, viewport
;
38 var HEADER
= ":link{ie7-link:link}:visited{ie7-link:visited}";
40 // -----------------------------------------------------------------------
42 // -----------------------------------------------------------------------
44 var RELATIVE
= /^[\w\.]+[^:]*$/;
45 function makePath(href
, path
) {
46 if (RELATIVE
.test(href
)) href
= (path
|| "") + href
;
50 function getPath(href
, path
) {
51 href
= makePath(href
, path
);
52 return href
.slice(0, href
.lastIndexOf("/") + 1);
55 // Get the path to this script
56 var script
= document
.scripts
[document
.scripts
.length
- 1];
57 var path
= getPath(script
.src
);
59 // Use microsoft's http request object to load external files
61 var httpRequest
= new ActiveXObject("Microsoft.XMLHTTP");
67 function loadFile(href
, path
) {
69 href
= makePath(href
, path
);
70 if (!fileCache
[href
]) {
71 httpRequest
.open("GET", href
, false);
73 if (httpRequest
.status
== 0 || httpRequest
.status
== 200) {
74 fileCache
[href
] = httpRequest
.responseText
;
80 return fileCache
[href
] || "";
83 // -----------------------------------------------------------------------
85 // -----------------------------------------------------------------------
88 // This is a cut-down version of base2 (http://code.google.com/p/base2/)
90 var _slice
= Array
.prototype.slice
;
93 var _FORMAT
= /%([1-9])/g;
94 var _LTRIM
= /^\s\s*/;
95 var _RTRIM
= /\s\s*$/;
96 var _RESCAPE
= /([\/()[\]{}|*+-.,^$?\\])/g; // safe regular expressions
97 var _BASE
= /\bbase\b/;
98 var _HIDDEN
= ["constructor", "toString"]; // only override these when prototyping
103 Base
.extend = function(_instance
, _static
) {
104 // Build the prototype.
106 var _prototype
= new this;
107 extend(_prototype
, _instance
);
110 // Create the wrapper for the constructor function.
111 var _constructor
= _prototype
.constructor;
113 // Don't call the constructor function when prototyping.
114 if (!prototyping
) _constructor
.apply(this, arguments
);
116 _prototype
.constructor = klass
;
118 // Build the static interface.
119 klass
.extend
= arguments
.callee
;
120 extend(klass
, _static
);
121 klass
.prototype = _prototype
;
124 Base
.prototype.extend = function(source
) {
125 return extend(this, source
);
129 // A collection of regular expressions and their associated replacement values.
130 // A Base class for creating parsers.
137 var REGGRP_BACK_REF
= /\\(\d+)/g,
138 REGGRP_ESCAPE_COUNT
= /\[(\\.|[^\]\\])+\]|\\.|\(\?/g,
139 REGGRP_PAREN
= /\(/g,
140 REGGRP_LOOKUP
= /\$(\d+)/,
141 REGGRP_LOOKUP_SIMPLE
= /^\$\d+$/,
142 REGGRP_LOOKUPS
= /(\[(\\.|[^\]\\])+\]|\\.|\(\?)|\(/g,
143 REGGRP_DICT_ENTRY
= /^<#\w+>$/,
144 REGGRP_DICT_ENTRIES
= /<#(\w+)>/g;
146 var RegGrp
= Base
.extend({
147 constructor: function(values
) {
156 add: function(expression
, replacement
) {
157 delete this[COMPILED
];
158 if (expression
instanceof RegExp
) {
159 expression
= expression
.source
;
161 if (!this[HASH
+ expression
]) this[KEYS
].push(String(expression
));
162 return this[ITEMS
][HASH
+ expression
] = new RegGrp
.Item(expression
, replacement
, this);
165 compile: function(recompile
) {
166 if (recompile
|| !this[COMPILED
]) {
167 this[COMPILED
] = new RegExp(this, this.ignoreCase
? "gi" : "g");
169 return this[COMPILED
];
172 merge: function(values
) {
173 for (var i
in values
) this.add(i
, values
[i
]);
176 exec: function(string
) {
178 patterns
= group
[KEYS
],
179 items
= group
[ITEMS
], item
;
180 var result
= this.compile(true).exec(string
);
182 // Loop through the RegGrp items.
183 var i
= 0, offset
= 1;
184 while ((item
= items
[HASH
+ patterns
[i
++]])) {
185 var next
= offset
+ item
.length
+ 1;
186 if (result
[offset
]) { // do we have a result?
187 if (item
.replacement
=== 0) {
188 return group
.exec(string
);
190 var args
= result
.slice(offset
, next
), j
= args
.length
;
191 while (--j
) args
[j
] = args
[j
] || ""; // some platforms return null/undefined for non-matching sub-expressions
192 args
[0] = {match
: args
[0], item
: item
};
202 parse: function(string
) {
203 string
+= ""; // type safe
205 patterns
= group
[KEYS
],
206 items
= group
[ITEMS
];
207 return string
.replace(this.compile(), function(match
) {
208 var args
= [], item
, offset
= 1, i
= arguments
.length
;
209 while (--i
) args
[i
] = arguments
[i
] || ""; // some platforms return null/undefined for non-matching sub-expressions
210 // Loop through the RegGrp items.
211 while ((item
= items
[HASH
+ patterns
[i
++]])) {
212 var next
= offset
+ item
.length
+ 1;
213 if (args
[offset
]) { // do we have a result?
214 var replacement
= item
.replacement
;
215 switch (typeof replacement
) {
217 return replacement
.apply(group
, args
.slice(offset
, next
));
219 return args
[offset
+ replacement
];
230 toString: function() {
233 items
= this[ITEMS
], item
;
234 for (var i
= 0; item
= items
[HASH
+ keys
[i
]]; i
++) {
235 strings
[i
] = item
.source
;
237 return "(" + strings
.join(")|(") + ")";
240 IGNORE
: null, // a null replacement value means that there is no replacement.
243 constructor: function(source
, replacement
, owner
) {
244 var length
= source
.indexOf("(") === -1 ? 0 : RegGrp
.count(source
);
246 var dictionary
= owner
.dictionary
;
247 if (dictionary
&& source
.indexOf("<#") !== -1) {
248 if (REGGRP_DICT_ENTRY
.test(source
)) {
249 var entry
= dictionary
[ITEMS
][HASH
+ source
.slice(2, -1)];
250 source
= entry
.replacement
;
251 length
= entry
._length
;
253 source
= dictionary
.parse(source
);
257 if (typeof replacement
== "number") replacement
= String(replacement
);
258 else if (replacement
== null) replacement
= 0;
260 // Does the expression use sub-expression lookups?
261 if (typeof replacement
== "string" && REGGRP_LOOKUP
.test(replacement
)) {
262 if (REGGRP_LOOKUP_SIMPLE
.test(replacement
)) { // A simple lookup? (e.g. "$2").
263 // Store the index (used for fast retrieval of matched strings).
264 var index
= replacement
.slice(1) - 0;
265 if (index
&& index
<= length
) replacement
= index
;
267 // A complicated lookup (e.g. "Hello $2 $1.").
268 var lookup
= replacement
, regexp
;
269 replacement = function(match
) {
271 regexp
= new RegExp(source
, "g" + (this.ignoreCase
? "i": ""));
273 return match
.replace(regexp
, lookup
);
278 this.length
= length
;
279 this.source
= String(source
);
280 this.replacement
= replacement
;
284 count: function(expression
) {
285 return (String(expression
).replace(REGGRP_ESCAPE_COUNT
, "").match(REGGRP_PAREN
) || "").length
;
289 var Dictionary
= RegGrp
.extend({
290 parse: function(phrase
) {
291 // Prevent sub-expressions in dictionary entries from capturing.
292 var entries
= this[ITEMS
];
293 return phrase
.replace(REGGRP_DICT_ENTRIES
, function(match
, entry
) {
294 entry
= entries
[HASH
+ entry
];
295 return entry
? entry
._nonCapturing
: match
;
299 add: function(expression
, replacement
) {
300 // Get the underlying replacement value.
301 if (replacement
instanceof RegExp
) {
302 replacement
= replacement
.source
;
304 // Translate the replacement.
305 // The result is the original replacement recursively parsed by this dictionary.
306 var nonCapturing
= replacement
.replace(REGGRP_LOOKUPS
, _nonCapture
);
307 if (replacement
.indexOf("(") !== -1) {
308 var realLength
= RegGrp
.count(replacement
);
310 if (replacement
.indexOf("<#") !== -1) {
311 replacement
= this.parse(replacement
);
312 nonCapturing
= this.parse(nonCapturing
);
314 var item
= this.base(expression
, replacement
);
315 item
._nonCapturing
= nonCapturing
;
316 item
._length
= realLength
|| item
.length
; // underlying number of sub-groups
320 toString: function() {
321 return "(<#" + this[PATTERNS
].join(">)|(<#") + ">)";
325 function _nonCapture(match
, escaped
) {
326 return escaped
|| "(?:"; // non-capturing
329 // =========================================================================
331 // =========================================================================
333 function extend(object
, source
) { // or extend(object, key, value)
334 if (object
&& source
) {
335 var proto
= (typeof source
== "function" ? Function
: Object
).prototype;
336 // Add constructor, toString etc
337 var i
= _HIDDEN
.length
, key
;
338 if (prototyping
) while (key
= _HIDDEN
[--i
]) {
339 var value
= source
[key
];
340 if (value
!= proto
[key
]) {
341 if (_BASE
.test(value
)) {
342 _override(object
, key
, value
)
348 // Copy each of the source object's properties to the target object.
349 for (key
in source
) if (typeof proto
[key
] == "undefined") {
350 var value
= source
[key
];
351 // Check for method overriding.
352 if (object
[key
] && typeof value
== "function" && _BASE
.test(value
)) {
353 _override(object
, key
, value
);
362 function _override(object
, name
, method
) {
363 // Override an existing method.
364 var ancestor
= object
[name
];
365 object
[name
] = function() {
366 var previous
= this.base
;
367 this.base
= ancestor
;
368 var returnValue
= method
.apply(this, arguments
);
369 this.base
= previous
;
374 function combine(keys
, values
) {
375 // Combine two arrays to make a hash.
376 if (!values
) values
= keys
;
378 for (var i
in keys
) hash
[i
] = values
[i
];
382 function format(string
) {
383 // Replace %n with arguments[n].
384 // e.g. format("%1 %2%3 %2a %1%3", "she", "se", "lls");
385 // ==> "she sells sea shells"
386 // Only %1 - %9 supported.
387 var args
= arguments
;
388 var _FORMAT
= new RegExp("%([1-" + arguments
.length
+ "])", "g");
389 return String(string
).replace(_FORMAT
, function(match
, index
) {
390 return index
< args
.length
? args
[index
] : match
;
394 function match(string
, expression
) {
395 // Same as String.match() except that this function will return an empty
396 // array if there is no match.
397 return String(string
).match(expression
) || [];
400 function rescape(string
) {
401 // Make a string safe for creating a RegExp.
402 return String(string
).replace(_RESCAPE
, "\\$1");
405 // http://blog.stevenlevithan.com/archives/faster-trim-javascript
406 function trim(string
) {
407 return String(string
).replace(_LTRIM
, "").replace(_RTRIM
, "");
416 // -----------------------------------------------------------------------
418 // -----------------------------------------------------------------------
420 var Parser
= RegGrp
.extend({ignoreCase
: true});
422 var SINGLE_QUOTES
= /'/g,
423 ESCAPED = /'(\d
+)'/g,
425 UNESCAPE = /\\([nrtf'"])/g;
429 var encoder = new Parser({
431 "<!\\-\\-|\\-\\->": "",
432 "\\/\\*[^*]*\\*+([^\\/][^*]*\\*+)*\\/": "",
434 "@(namespace|import)[^;\\n
]+[;\\n
]": "",
436 "'(\\\\.|[^'\\\\])*'": encodeString,
437 '"(\\\\.|[^"\\\\])*"': encodeString,
442 function encode(selector) {
443 return encoder.parse(selector).replace(UNESCAPE, "$1");
446 function decode(query) {
447 // put string values back
448 return query.replace(ESCAPED, decodeString);
451 function encodeString(string) {
452 var index = strings.length;
453 strings[index] = string.slice(1, -1)
454 .replace(UNESCAPE, "$1")
455 .replace(SINGLE_QUOTES, "\\'");
456 return "'" + index + "'";
459 function decodeString(match, index) {
460 var string = strings[index];
461 if (string == null) return match;
462 return "'" + strings[index] + "'";
465 function getString(value) {
466 return value.indexOf("'") === 0 ? strings[value.slice(1, - 1)] : value;
469 // clone a "width
" function to create a "height
" function
470 var rotater = new RegGrp({
480 function rotate(fn) {
481 return rotater.parse(fn);
484 // -----------------------------------------------------------------------
486 // -----------------------------------------------------------------------
488 var eventHandlers = [];
490 function addResize(handler) {
492 addEventHandler(window, "onresize
", handler);
495 // add an event handler (function) to an element
496 function addEventHandler(element, type, handler) {
497 element.attachEvent(type, handler);
498 // store the handler so it can be detached later
499 eventHandlers.push(arguments);
502 // remove an event handler assigned to an element by IE7
503 function removeEventHandler(element, type, handler) {
505 element.detachEvent(type, handler);
507 // write a letter of complaint to microsoft..
511 // remove event handlers (they eat memory)
512 addEventHandler(window, "onunload
", function() {
514 while (handler = eventHandlers.pop()) {
515 removeEventHandler(handler[0], handler[1], handler[2]);
519 function register(handler, element, condition) { // -@DRE
520 //var set = handler[element.uniqueID];
521 if (!handler.elements) handler.elements = {};
522 if (condition) handler.elements[element.uniqueID] = element;
523 else delete handler.elements[element.uniqueID];
524 //return !set && condition;
528 addEventHandler(window, "onbeforeprint
", function() {
529 if (!IE7.CSS.print) new StyleSheet("print
");
530 IE7.CSS.print.recalc();
533 // -----------------------------------------------------------------------
535 // -----------------------------------------------------------------------
537 // this is handy because it means that web developers can mix and match
538 // measurement units in their style sheets. it is not uncommon to
539 // express something like padding in "em
" units whilst border thickness
540 // is most often expressed in pixels.
542 var PIXEL = /^\d+(px)?$/i;
543 var PERCENT = /^\d+%$/;
544 var getPixelValue = function(element, value) {
545 if (PIXEL.test(value)) return parseInt(value);
546 var style = element.style.left;
547 var runtimeStyle = element.runtimeStyle.left;
548 element.runtimeStyle.left = element.currentStyle.left;
549 element.style.left = value || 0;
550 value = element.style.pixelLeft;
551 element.style.left = style;
552 element.runtimeStyle.left = runtimeStyle;
556 // -----------------------------------------------------------------------
558 // -----------------------------------------------------------------------
562 var Fix = Base.extend({
563 constructor: function() {
570 // a store for functions that will be called when refreshing IE7
572 function addRecalc(recalc) {
573 recalcs.push(recalc);
576 IE7.recalc = function() {
578 // re-apply style sheet rules (re-calculate ie7 classes)
580 // apply global fixes to the document
581 for (var i = 0; i < recalcs.length; i++) recalcs[i]();
584 function isFixed(element) {
585 return element.currentStyle["ie7
-position
"] == "fixed
";
589 function getDefinedStyle(element, propertyName) {
590 return element.currentStyle[$IE7 + propertyName] || element.currentStyle[propertyName];
593 function setOverrideStyle(element, propertyName, value) {
594 if (element.currentStyle[$IE7 + propertyName] == null) {
595 element.runtimeStyle[$IE7 + propertyName] = element.currentStyle[propertyName];
597 element.runtimeStyle[propertyName] = value;
600 // Create a temporary element which is used to inherit styles
601 // from the target element.
602 function createTempElement(tagName) {
603 var element = document.createElement(tagName || "object
");
604 element.style.cssText = "position
:absolute
;padding
:0;display
:block
;border
:none
;clip
:rect(0 0 0 0);left
:-9999";
605 element.ie7_anon = true;
610 // =========================================================================
612 // =========================================================================
614 var NEXT_SIBLING = "(e
.nextSibling
&&IE7
._getElementSibling(e
,'next'))",
615 PREVIOUS_SIBLING = NEXT_SIBLING.replace(/next/g, "previous
"),
616 IS_ELEMENT = "e
.nodeName
>'@'",
617 IF_ELEMENT = "if(" + IS_ELEMENT + "){";
619 var ID_ATTRIBUTE = "(e
.nodeName
==='FORM'?IE7
._getAttribute(e
,'id'):e
.id
)";
621 var HYPERLINK = /a(#[\w-]+)?(\.[\w-]+)?:(hover|active)/i;
622 var FIRST_LINE_LETTER = /(.*)(:first-(line|letter))/;
624 var RULE = /((?:\\.|[^{\\])+)\{((?:\\.|[^}\\])+)\}/g;
625 var SELECTOR = /(?:\\.|[^,\\])+/g;
627 var styleSheets = document.styleSheets;
629 var inheritedProperties = [];
631 IE7.CSS = new (Fix.extend({ // single instance
637 pseudoClasses: appVersion < 7 ? "first
\\-child
" : "",
638 dynamicPseudoClasses: {
639 toString: function() {
641 for (var pseudoClass in this) strings.push(pseudoClass);
642 return strings.join("|");
648 var CLASS = "\\[class=?[^\\]]*\\]";
649 var pseudoClasses = [];
650 if (this.pseudoClasses) pseudoClasses.push(this.pseudoClasses);
651 var dynamicPseudoClasses = this.dynamicPseudoClasses.toString();
652 if (dynamicPseudoClasses) pseudoClasses.push(dynamicPseudoClasses);
653 pseudoClasses = pseudoClasses.join("|");
654 var unknown = appVersion < 7 ? ["[>+~\\[(]|([:.])[\\w
-]+\\1"] : [CLASS];
655 if (pseudoClasses) unknown.push(":(" + pseudoClasses + ")");
656 this.UNKNOWN = new RegExp(unknown.join("|") || NONE, "i
");
657 var complex = appVersion < 7 ? ["\\[[^\\]]+\\]|[^\\s(\\[]+\\s
*[+~]"] : [CLASS];
658 var complexRule = complex.concat();
659 if (pseudoClasses) complexRule.push(":(" + pseudoClasses + ")");
660 Rule.COMPLEX = new RegExp(complexRule.join("|") || NONE, "ig
");
661 if (this.pseudoClasses) complex.push(":(" + this.pseudoClasses + ")");
662 DynamicRule.COMPLEX = new RegExp(complex.join("|") || NONE, "i
");
663 dynamicPseudoClasses = "not
\\(:" + dynamicPseudoClasses.split("|").join("\\)|not
\\(:") + "\\)|" + dynamicPseudoClasses;
664 DynamicRule.MATCH = new RegExp(dynamicPseudoClasses ? "(.*?):(" + dynamicPseudoClasses + ")(.*)" : NONE, "i
");
666 this.createStyleSheet();
670 addEventHandler: function() {
671 addEventHandler.apply(null, arguments);
674 addFix: function(expression, replacement) {
675 this.parser.add(expression, replacement);
678 addRecalc: function(propertyName, test, handler, replacement) {
679 // recalcs occur whenever the document is refreshed using document.recalc()
680 propertyName = propertyName.source || propertyName;
681 test = new RegExp("([{;\\s
])" + propertyName + "\\s
*:\\s
*" + test + "[^;}]*");
682 var id = this.recalcs.length;
683 if (typeof replacement == "string
") replacement = propertyName + ":" + replacement;
684 this.addFix(test, function(match) {
685 if (typeof replacement == "function") replacement = replacement(match);
686 return (replacement ? replacement : match) + ";ie7
-" + match.slice(1) + ";ie7_recalc
" + id + ":1";
688 this.recalcs.push(arguments);
694 new StyleSheet("screen
");
698 createStyleSheet: function() {
699 // create the IE7 style sheet
700 document.getElementsByTagName("head
")[0].appendChild(document.createElement("style
"));
701 this.styleSheet = styleSheets[styleSheets.length - 1];
702 // flag it so we can ignore it during parsing
703 this.styleSheet.ie7 = true;
704 this.styleSheet.owningElement.ie7 = true;
705 this.styleSheet.cssText = HEADER;
708 getInlineCSS: function() {// load inline styles
709 var styleSheets = document.getElementsByTagName("style
"), styleSheet;
710 for (var i = styleSheets.length - 1; styleSheet = styleSheets[i]; i--) {
711 if (!styleSheet.disabled && !styleSheet.ie7) {
712 styleSheet._cssText = styleSheet.innerHTML;
717 getText: function(styleSheet, path) {
718 // Internet Explorer will trash unknown selectors (it converts them to "UNKNOWN
").
719 // So we must reload external style sheets (internal style sheets can have their text
720 // extracted through the innerHTML property).
722 // load the style sheet text from an external file
724 var cssText = styleSheet.cssText;
728 if (httpRequest) cssText = loadFile(styleSheet.href, path) || cssText;
733 this.screen.recalc();
734 // we're going to read through all style rules.
735 // certain rules have had ie7 properties added to them.
736 // e.g. p{top:0; ie7_recalc2:1; left:0}
737 // this flags a property in the rule as needing a fix.
738 // the selector text is then used to query the document.
739 // we can then loop through the results of the query
740 // and fix the elements.
741 // we ignore the IE7 rules - so count them in the header
742 var RECALCS = /ie7_recalc\d+/g;
743 var start = HEADER.match(/[{,]/g).length;
744 // only calculate screen fixes. print fixes don't show up anyway
745 var rules = this.styleSheet.rules, rule;
746 var calcs, calc, elements, element, i, j, k, id;
747 // loop through all rules
748 for (i = start; rule = rules[i]; i++) {
749 var cssText = rule.style.cssText;
750 // search for the "ie7_recalc
" flag (there may be more than one)
751 if (calcs = cssText.match(RECALCS)) {
752 // use the selector text to query the document
753 elements = cssQuery(rule.selectorText);
754 // if there are matching elements then loop
755 // through the recalc functions and apply them
757 if (elements.length) for (j = 0; j < calcs.length; j++) {
758 // get the matching flag (e.g. ie7_recalc3)
760 // extract the numeric id from the end of the flag
761 // and use it to index the collection of recalc
763 calc = IE7.CSS.recalcs[id.slice(10)][2];
764 for (k = 0; (element = elements[k]); k++) {
766 if (element.currentStyle[id]) calc(element, cssText);
773 refresh: function() {
774 this.styleSheet.cssText = HEADER + this.screen + this.print;
778 // trash the old style sheets
779 for (var i = 0; i < styleSheets.length; i++) {
780 if (!styleSheets[i].ie7) {
782 var cssText = styleSheets[i].cssText;
786 if (cssText) styleSheets[i].cssText = "";
792 // -----------------------------------------------------------------------
793 // IE7 StyleSheet class
794 // -----------------------------------------------------------------------
796 var StyleSheet = Base.extend({
797 constructor: function(media) {
800 IE7.CSS[media] = this;
804 createRule: function(selector, cssText) {
806 if (PseudoElement && (match = selector.match(PseudoElement.MATCH))) {
807 return new PseudoElement(match[1], match[2], cssText);
808 } else if (match = selector.match(DynamicRule.MATCH)) {
809 if (!HYPERLINK.test(match[0]) || DynamicRule.COMPLEX.test(match[0])) {
810 return new DynamicRule(selector, match[1], match[2], match[3], cssText);
813 return new Rule(selector, cssText);
815 return selector + " {" + cssText + "}";
818 getText: function() {
819 // store for style sheet text
820 // parse media decalarations
821 var MEDIA = /@media\s+([^{]+?)\s*\{([^@]+\})\s*\}/gi;
822 var IMPORTS = /@import[^;\n]+/gi;
823 var TRIM_IMPORTS = /@import\s+url\s*\(\s*["']?|["']?\s
*\)\s*/gi
;
824 var URL
= /(url\s*\(\s*['"]?)([\w\.]+[^:\)]*['"]?\))/gi;
828 // Store loaded cssText URLs
831 function getCSSText(styleSheet
, path
, media
, level
) {
834 media
= toSimpleMedia(styleSheet
.media
);
837 if (media
=== "none") {
838 styleSheet
.disabled
= true;
841 if (media
=== "all" || media
=== self
.media
) {
842 // IE only allows importing style sheets three levels deep.
843 // it will crash if you try to access a level below this
844 if (level
< 3 && styleSheet
.cssText
) {
845 var hrefs
= styleSheet
.cssText
.match(IMPORTS
);
846 // loop through imported style sheets
847 for (var i
= 0, imported
; i
< styleSheet
.imports
.length
; i
++) {
848 var imported
= styleSheet
.imports
[i
];
849 var href
= styleSheet
._href
|| styleSheet
.href
;
850 imported
._href
= hrefs
[i
].replace(TRIM_IMPORTS
, "");
851 // call this function recursively to get all imported style sheets
852 cssText
+= getCSSText(imported
, getPath(href
, path
), media
, level
+ 1);
855 // retrieve inline style or load an external style sheet
856 cssText
+= encode(styleSheet
.href
? loadStyleSheet(styleSheet
, path
) : styleSheet
.owningElement
._cssText
);
857 cssText
= parseMedia(cssText
, self
.media
);
862 // Load all style sheets in the document
863 for (var i
= 0; i
< styleSheets
.length
; i
++) {
864 var styleSheet
= styleSheets
[i
];
865 if (!styleSheet
.disabled
&& !styleSheet
.ie7
) this.cssText
+= getCSSText(styleSheet
);
869 function parseMedia(cssText
, media
) {
870 filterMedia
.value
= media
;
871 return cssText
.replace(MEDIA
, filterMedia
);
874 function filterMedia(match
, media
, cssText
) {
875 media
= toSimpleMedia(media
);
879 if (media
!== filterMedia
.value
) return "";
886 function toSimpleMedia(media
) {
887 if (!media
) return "all";
888 var split
= media
.toLowerCase().split(/\s*,\s*/);
890 for (var i
= 0; i
< split
.length
; i
++) {
891 if (split
[i
] === "all") return "all";
892 if (split
[i
] === "screen") {
893 if (media
=== "print") return "all";
895 } else if (split
[i
] === "print") {
896 if (media
=== "screen") return "all";
903 // Load an external style sheet
904 function loadStyleSheet(styleSheet
, path
) {
905 var href
= styleSheet
._href
|| styleSheet
.href
;
906 var url
= makePath(href
, path
);
907 // If the style sheet has already loaded then don't reload it
908 if (fileCache
[url
]) return "";
910 fileCache
[url
] = styleSheet
.disabled
? "" :
911 fixUrls(IE7
.CSS
.getText(styleSheet
, path
), getPath(href
, path
));
912 return fileCache
[url
];
916 // We're lumping all css text into one big style sheet so relative
917 // paths have to be fixed. This is necessary anyway because of other
918 // Internet Explorer bugs.
919 function fixUrls(cssText
, pathname
) {
921 return cssText
.replace(URL
, "$1" + pathname
.slice(0, pathname
.lastIndexOf("/") + 1) + "$2");
929 if (inheritedProperties
.length
) {
930 this.cssText
= parseInherited(this.cssText
);
932 this.cssText
= decode(this.cssText
);
937 this.cssText
= IE7
.CSS
.parser
.parse(this.cssText
);
939 // Parse the style sheet
940 var offset
= IE7
.CSS
.rules
.length
;
941 var rules
= [], rule
;
942 while ((rule
= RULE
.exec(this.cssText
))) {
943 var cssText
= rule
[2];
945 var fixDescendants
= appVersion
< 7 && cssText
.indexOf("AlphaImageLoader") !== -1;
946 var selectors
= rule
[1].match(SELECTOR
), selector
;
947 for (var i
= 0; selector
= selectors
[i
]; i
++) {
948 selector
= trim(selector
);
949 var isUnknown
= IE7
.CSS
.UNKNOWN
.test(selector
);
950 selectors
[i
] = isUnknown
? this.createRule(selector
, cssText
) : selector
+ "{" + cssText
+ "}";
951 if (fixDescendants
) selectors
[i
] += this.createRule(selector
+ ">*", "position:relative");
953 rules
.push(selectors
.join("\n"));
956 this.cssText
= rules
.join("\n");
957 this.rules
= IE7
.CSS
.rules
.slice(offset
);
962 for (i
= 0; (rule
= this.rules
[i
]); i
++) rule
.recalc();
965 toString: function() {
966 return "@media " + this.media
+ "{" + this.cssText
+ "}";
972 // -----------------------------------------------------------------------
974 // -----------------------------------------------------------------------
976 var Rule
= IE7
.Rule
= Base
.extend({
977 constructor: function(selector
, cssText
) {
978 this.id
= IE7
.CSS
.rules
.length
;
979 this.className
= Rule
.PREFIX
+ this.id
;
980 var pseudoElement
= selector
.match(FIRST_LINE_LETTER
);
981 this.selector
= (pseudoElement
? pseudoElement
[1] : selector
) || "*";
982 this.selectorText
= this.parse(this.selector
) + (pseudoElement
? pseudoElement
[2] : "");
983 this.cssText
= cssText
;
984 this.MATCH
= new RegExp("\\s" + this.className
+ "(\\s|$)", "g");
985 IE7
.CSS
.rules
.push(this);
991 add: function(element
) {
992 // allocate this class
993 element
.className
+= " " + this.className
;
997 // execute the underlying css query for this class
998 var match
= cssQuery(this.selector
);
999 // add the class name for all matching elements
1000 for (var i
= 0; i
< match
.length
; i
++) this.add(match
[i
]);
1003 parse: function(selector
) {
1004 // attempt to preserve specificity for "loose" parsing by
1005 // removing unknown tokens from a css selector but keep as
1007 var simple
= selector
.replace(Rule
.CHILD
, " ").replace(Rule
.COMPLEX
, "");
1008 if (appVersion
< 7) simple
= simple
.replace(Rule
.MULTI
, "");
1009 var tags
= match(simple
, Rule
.TAGS
).length
- match(selector
, Rule
.TAGS
).length
;
1010 var classes
= match(simple
, Rule
.CLASSES
).length
- match(selector
, Rule
.CLASSES
).length
+ 1;
1011 while (classes
> 0 && Rule
.CLASS
.test(simple
)) {
1012 simple
= simple
.replace(Rule
.CLASS
, "");
1015 while (tags
> 0 && Rule
.TAG
.test(simple
)) {
1016 simple
= simple
.replace(Rule
.TAG
, "$1*");
1019 simple
+= "." + this.className
;
1020 classes
= Math
.min(classes
, 2);
1021 tags
= Math
.min(tags
, 2);
1022 var score
= -10 * classes
- tags
;
1024 simple
= simple
+ "," + Rule
.MAP
[score
] + " " + simple
;
1029 remove: function(element
) {
1030 // deallocate this class
1031 element
.className
= element
.className
.replace(this.MATCH
, "$1");
1034 toString: function() {
1035 return format("%1 {%2}", this.selectorText
, this.cssText
);
1041 MULTI
: /(\.[\w-]+)+/g,
1042 PREFIX
: "ie7_class",
1043 TAG
: /^\w+|([\s>+~])\w+/,
1044 TAGS
: /^\w|[\s>+~]\w/g,
1049 "11": "html.ie7_html",
1050 "12": "html.ie7_html body",
1051 "20": ".ie7_html .ie7_body",
1052 "21": "html.ie7_html .ie7_body",
1053 "22": "html.ie7_html body.ie7_body"
1057 // -----------------------------------------------------------------------
1058 // IE7 dynamic style
1059 // -----------------------------------------------------------------------
1061 // object properties:
1062 // attach: the element that an event handler will be attached to
1063 // target: the element that will have the IE7 class applied
1065 var DynamicRule
= Rule
.extend({
1067 constructor: function(selector
, attach
, dynamicPseudoClass
, target
, cssText
) {
1068 this.negated
= dynamicPseudoClass
.indexOf("not") === 0;
1069 if (this.negated
) dynamicPseudoClass
= dynamicPseudoClass
.slice(5, -1);
1070 // initialise object properties
1071 this.attach
= attach
|| "*";
1072 this.dynamicPseudoClass
= IE7
.CSS
.dynamicPseudoClasses
[dynamicPseudoClass
];
1073 this.target
= target
;
1074 this.base(selector
, cssText
);
1077 recalc: function() {
1078 // execute the underlying css query for this class
1079 var attaches
= cssQuery(this.attach
), attach
;
1081 for (var i
= 0; attach
= attaches
[i
]; i
++) {
1082 // retrieve the event handler's target element(s)
1083 var target
= this.target
? cssQuery(this.target
, attach
) : [attach
];
1084 // attach event handlers for dynamic pseudo-classes
1085 if (target
.length
) this.dynamicPseudoClass
.apply(attach
, target
, this);
1090 // -----------------------------------------------------------------------
1091 // IE7 dynamic pseudo-classes
1092 // -----------------------------------------------------------------------
1094 var DynamicPseudoClass
= Base
.extend({
1095 constructor: function(name
, apply
) {
1098 this.instances
= {};
1099 IE7
.CSS
.dynamicPseudoClasses
[name
] = this;
1102 register: function(instance
, negated
) {
1103 // an "instance" is actually an Arguments object
1104 var _class
= instance
[2];
1105 if (!negated
&& _class
.negated
) {
1106 this.unregister(instance
, true);
1108 instance
.id
= _class
.id
+ instance
[0].uniqueID
;
1109 if (!this.instances
[instance
.id
]) {
1110 var target
= instance
[1], j
;
1111 for (j
= 0; j
< target
.length
; j
++) _class
.add(target
[j
]);
1112 this.instances
[instance
.id
] = instance
;
1117 unregister: function(instance
, negated
) {
1118 var _class
= instance
[2];
1119 if (!negated
&& _class
.negated
) {
1120 this.register(instance
, true);
1122 if (this.instances
[instance
.id
]) {
1123 var target
= instance
[1], j
;
1124 for (j
= 0; j
< target
.length
; j
++) _class
.remove(target
[j
]);
1125 delete this.instances
[instance
.id
];
1131 // -----------------------------------------------------------------------
1132 // dynamic pseudo-classes
1133 // -----------------------------------------------------------------------
1135 if (appVersion
< 7) {
1136 var Hover
= new DynamicPseudoClass("hover", function(element
) {
1137 var instance
= arguments
;
1138 IE7
.CSS
.addEventHandler(element
, "onmouseenter", function() {
1139 Hover
.register(instance
);
1141 IE7
.CSS
.addEventHandler(element
, "onmouseleave", function() {
1142 Hover
.unregister(instance
);
1146 // globally trap the mouseup event (thanks Martijn!)
1147 addEventHandler(document
, "onmouseup", function() {
1148 var instances
= Hover
.instances
;
1149 for (var i
in instances
)
1150 if (!instances
[i
][0].contains(event
.srcElement
))
1151 Hover
.unregister(instances
[i
]);
1156 "=": "%1==='%2'", // "[@%1='%2']"
1157 "~=": "(' '+%1+' ').indexOf(' %2 ')!==-1", // "[contains(concat(' ',@%1,' '),' %2 ')]",
1158 "|=": "%1==='%2'||%1.indexOf('%2-')===0", // "[@%1='%2' or starts-with(@%1,'%2-')]",
1159 "^=": "%1.indexOf('%2')===0", // "[starts-with(@%1,'%2')]",
1160 "$=": "%1.slice(-'%2'.length)==='%2'", // "[ends-with(@%1,'%2')]",
1161 "*=": "%1.indexOf('%2')!==-1" // "[contains(@%1,'%2')]"
1163 ATTR
[""] = "%1!=null"; // "[@%1]"
1166 "<#attr>": function(match
, name
, operator
, value
) {
1167 var attr
= "IE7._getAttribute(e,'" + name
+ "')";
1168 value
= getString(value
);
1169 if (operator
.length
> 1) {
1170 if (!value
|| operator
=== "~=" && SPACE
.test(value
)) {
1173 attr
= "(" + attr
+ "||'')";
1175 return "(" + format(ATTR
[operator
], attr
, value
) + ")&&";
1178 "<#id>": ID_ATTRIBUTE
+ "==='$1'&&",
1180 "<#class>": "e.className&&(' '+e.className+' ').indexOf(' $1 ')!==-1&&",
1183 ":first-child": "!" + PREVIOUS_SIBLING
+ "&&",
1184 ":link": "e.href&&(e.nodeName==='A'||e.nodeName==='AREA')&&",
1185 ":visited": "false&&" // not implemented (security)
1188 // =========================================================================
1190 // =========================================================================
1192 // default font-sizes
1193 //HEADER += "h1{font-size:2em}h2{font-size:1.5em;}h3{font-size:1.17em;}h4{font-size:1em}h5{font-size:.83em}h6{font-size:.67em}";
1195 IE7
.HTML
= new (Fix
.extend({ // single instance
1200 addFix: function() {
1201 // fixes are a one-off, they are applied when the document is loaded
1202 this.fixes
.push(arguments
);
1206 for (var i
= 0; i
< this.fixes
.length
; i
++) {
1207 var match
= cssQuery(this.fixes
[i
][0]);
1208 var fix
= this.fixes
[i
][1];
1209 for (var j
= 0; j
< match
.length
; j
++) fix(match
[j
]);
1213 addRecalc: function() {
1214 // recalcs occur whenever the document is refreshed using document.recalc()
1215 this.recalcs
.push(arguments
);
1218 recalc: function() {
1219 // loop through the fixes
1220 for (var i
= 0; i
< this.recalcs
.length
; i
++) {
1221 var match
= cssQuery(this.recalcs
[i
][0]);
1222 var recalc
= this.recalcs
[i
][1], element
;
1223 var key
= Math
.pow(2, i
);
1224 for (var j
= 0; (element
= match
[j
]); j
++) {
1225 var uniqueID
= element
.uniqueID
;
1226 if ((this.fixed
[uniqueID
] & key
) === 0) {
1227 element
= recalc(element
) || element
;
1228 this.fixed
[uniqueID
] |= key
;
1235 if (appVersion
< 7) {
1236 // provide support for the <abbr> tag.
1237 document
.createElement("abbr");
1239 // bind to the first child control
1240 IE7
.HTML
.addRecalc("label", function(label
) {
1241 if (!label
.htmlFor
) {
1242 var firstChildControl
= cssQuery("input,textarea", label
, true);
1243 if (firstChildControl
) {
1244 addEventHandler(label
, "onclick", function() {
1245 firstChildControl
.click();
1252 // =========================================================================
1254 // =========================================================================
1256 var NUMERIC
= "[.\\d]";
1259 var layout
= IE7
.Layout
= {};
1261 // big, ugly box-model hack + min/max stuff
1263 // #tantek > #erik > #dean { voice-family: hacker; }
1265 // -----------------------------------------------------------------------
1267 // -----------------------------------------------------------------------
1269 HEADER
+= "*{boxSizing:content-box}";
1271 // give an element "layout"
1272 layout
.boxSizing = function(element
) {
1273 if (!element
.currentStyle
.hasLayout
) {
1274 //# element.runtimeStyle.fixedHeight =
1275 element
.style
.height
= "0cm";
1276 if (element
.currentStyle
.verticalAlign
=== "auto")
1277 element
.runtimeStyle
.verticalAlign
= "top";
1278 // when an element acquires "layout", margins no longer collapse correctly
1279 collapseMargins(element
);
1283 // -----------------------------------------------------------------------
1285 // -----------------------------------------------------------------------
1287 function collapseMargins(element
) {
1288 if (element
!= viewport
&& element
.currentStyle
.position
!== "absolute") {
1289 collapseMargin(element
, "marginTop");
1290 collapseMargin(element
, "marginBottom");
1294 function collapseMargin(element
, type
) {
1295 if (!element
.runtimeStyle
[type
]) {
1296 var parentElement
= element
.parentElement
;
1297 var isTopMargin
= type
=== "marginTop";
1298 if (parentElement
&& parentElement
.currentStyle
.hasLayout
&& !IE7
._getElementSibling(element
, isTopMargin
? "previous" : "next")) return;
1299 var child
= element
[isTopMargin
? "firstChild" : "lastChild"];
1300 if (child
&& child
.nodeName
< "@") child
= IE7
._getElementSibling(child
, isTopMargin
? "next" : "previous");
1301 if (child
&& child
.currentStyle
.styleFloat
=== "none" && child
.currentStyle
.hasLayout
) {
1302 collapseMargin(child
, type
);
1303 margin
= _getMargin(element
, element
.currentStyle
[type
]);
1304 childMargin
= _getMargin(child
, child
.currentStyle
[type
]);
1305 if (margin
< 0 || childMargin
< 0) {
1306 element
.runtimeStyle
[type
] = margin
+ childMargin
;
1308 element
.runtimeStyle
[type
] = Math
.max(childMargin
, margin
);
1310 child
.runtimeStyle
[type
] = "0px";
1315 function _getMargin(element
, value
) {
1316 return value
=== "auto" ? 0 : getPixelValue(element
, value
);
1319 // -----------------------------------------------------------------------
1321 // -----------------------------------------------------------------------
1324 var UNIT
= /^[.\d][\w]*$/, AUTO
= /^(auto|0cm)$/;
1327 layout
.borderBox = function(element
){
1328 apply
.Width(element
);
1329 apply
.Height(element
);
1332 var _fixWidth = function(HEIGHT
) {
1333 apply
.Width = function(element
) {
1334 if (!PERCENT
.test(element
.currentStyle
.width
)) _fixWidth(element
);
1335 if (HEIGHT
) collapseMargins(element
);
1338 function _fixWidth(element
, value
) {
1339 if (!element
.runtimeStyle
.fixedWidth
) {
1340 if (!value
) value
= element
.currentStyle
.width
;
1341 element
.runtimeStyle
.fixedWidth
= UNIT
.test(value
) ? Math
.max(0, getFixedWidth(element
, value
)) + "px" : value
;
1342 setOverrideStyle(element
, "width", element
.runtimeStyle
.fixedWidth
);
1346 function layoutWidth(element
) {
1347 if (!isFixed(element
)) {
1348 var layoutParent
= element
.offsetParent
;
1349 while (layoutParent
&& !layoutParent
.currentStyle
.hasLayout
) layoutParent
= layoutParent
.offsetParent
;
1351 return (layoutParent
|| viewport
).clientWidth
;
1354 function getPixelWidth(element
, value
) {
1355 if (PERCENT
.test(value
)) return parseInt(parseFloat(value
) / 100 * layoutWidth(element
));
1356 return getPixelValue(element
, value
);
1359 var getFixedWidth = function(element
, value
) {
1360 var borderBox
= element
.currentStyle
["ie7-box-sizing"] === "border-box";
1362 if (MSIE5
&& !borderBox
)
1363 adjustment
+= getBorderWidth(element
) + getWidth(element
, "padding");
1364 else if (!MSIE5
&& borderBox
)
1365 adjustment
-= getBorderWidth(element
) + getWidth(element
, "padding");
1366 return getPixelWidth(element
, value
) + adjustment
;
1369 // easy way to get border thickness for elements with "layout"
1370 function getBorderWidth(element
) {
1371 return element
.offsetWidth
- element
.clientWidth
;
1374 // have to do some pixel conversion to get padding/margin thickness :-(
1375 function getWidth(element
, type
) {
1376 return getPixelWidth(element
, element
.currentStyle
[type
+ "Left"]) + getPixelWidth(element
, element
.currentStyle
[type
+ "Right"]);
1379 // -----------------------------------------------------------------------
1381 // -----------------------------------------------------------------------
1383 HEADER
+= "*{minWidth:none;maxWidth:none;min-width:none;max-width:none}";
1385 // handle min-width property
1386 layout
.minWidth = function(element
) {
1387 // IE6 supports min-height so we frig it here
1388 //#if (element.currentStyle.minHeight === "auto") element.runtimeStyle.minHeight = 0;
1389 if (element
.currentStyle
["min-width"] != null) {
1390 element
.style
.minWidth
= element
.currentStyle
["min-width"];
1392 if (register(arguments
.callee
, element
, element
.currentStyle
.minWidth
!== "none")) {
1393 layout
.boxSizing(element
);
1395 resizeWidth(element
);
1399 // clone the minWidth function to make a maxWidth function
1400 eval("IE7.Layout.maxWidth=" + String(layout
.minWidth
).replace(/min/g, "max"));
1402 // apply min/max restrictions
1403 function resizeWidth(element
) {
1405 if (element
== document
.body
) {
1406 var width
= element
.clientWidth
;
1408 var rect
= element
.getBoundingClientRect();
1409 width
= rect
.right
- rect
.left
;
1411 if (element
.currentStyle
.minWidth
!== "none" && width
< getFixedWidth(element
, element
.currentStyle
.minWidth
)) {
1412 element
.runtimeStyle
.width
= element
.currentStyle
.minWidth
;
1413 } else if (element
.currentStyle
.maxWidth
!== "none" && width
>= getFixedWidth(element
, element
.currentStyle
.maxWidth
)) {
1414 element
.runtimeStyle
.width
= element
.currentStyle
.maxWidth
;
1416 element
.runtimeStyle
.width
= element
.runtimeStyle
.fixedWidth
;
1420 // -----------------------------------------------------------------------
1422 // -----------------------------------------------------------------------
1424 function fixRight(element
) {
1425 if (register(fixRight
, element
, /^(fixed|absolute)$/.test(element
.currentStyle
.position
) &&
1426 getDefinedStyle(element
, "left") !== "auto" &&
1427 getDefinedStyle(element
, "right") !== "auto" &&
1428 AUTO
.test(getDefinedStyle(element
, "width")))) {
1429 resizeRight(element
);
1430 layout
.boxSizing(element
);
1433 layout
.fixRight
= fixRight
;
1435 function resizeRight(element
) {
1436 var left
= getPixelWidth(element
, element
.runtimeStyle
._left
|| element
.currentStyle
.left
);
1437 var width
= layoutWidth(element
) - getPixelWidth(element
, element
.currentStyle
.right
) - left
- getWidth(element
, "margin");
1438 if (parseInt(element
.runtimeStyle
.width
) === width
) return;
1439 element
.runtimeStyle
.width
= "";
1440 if (isFixed(element
) || HEIGHT
|| element
.offsetWidth
< width
) {
1441 if (!MSIE5
) width
-= getBorderWidth(element
) + getWidth(element
, "padding");
1442 if (width
< 0) width
= 0;
1443 element
.runtimeStyle
.fixedWidth
= width
;
1444 setOverrideStyle(element
, "width", width
);
1448 // -----------------------------------------------------------------------
1450 // -----------------------------------------------------------------------
1452 // handle window resize
1453 var clientWidth
= 0;
1454 addResize(function() {
1455 if (!viewport
) return;
1456 var i
, wider
= (clientWidth
< viewport
.clientWidth
);
1457 clientWidth
= viewport
.clientWidth
;
1458 // resize elements with "min-width" set
1459 var elements
= layout
.minWidth
.elements
;
1460 for (i
in elements
) {
1461 var element
= elements
[i
];
1462 var fixedWidth
= (parseInt(element
.runtimeStyle
.width
) === getFixedWidth(element
, element
.currentStyle
.minWidth
));
1463 if (wider
&& fixedWidth
) element
.runtimeStyle
.width
= "";
1464 if (wider
== fixedWidth
) resizeWidth(element
);
1466 // resize elements with "max-width" set
1467 var elements
= layout
.maxWidth
.elements
;
1468 for (i
in elements
) {
1469 var element
= elements
[i
];
1470 var fixedWidth
= (parseInt(element
.runtimeStyle
.width
) === getFixedWidth(element
, element
.currentStyle
.maxWidth
));
1471 if (!wider
&& fixedWidth
) element
.runtimeStyle
.width
= "";
1472 if (wider
!== fixedWidth
) resizeWidth(element
);
1474 // resize elements with "right" set
1475 for (i
in fixRight
.elements
) resizeRight(fixRight
.elements
[i
]);
1478 // -----------------------------------------------------------------------
1480 // -----------------------------------------------------------------------
1482 IE7
.CSS
.addRecalc("width", NUMERIC
, apply
.Width
);
1484 if (appVersion
< 7) {
1485 IE7
.CSS
.addRecalc("max-width", NUMERIC
, layout
.maxWidth
);
1486 IE7
.CSS
.addRecalc("right", NUMERIC
, fixRight
);
1487 } else if (appVersion
== 7) {
1488 if (HEIGHT
) IE7
.CSS
.addRecalc("height", "[\\d.]+%", function(element
) {
1489 element
.runtimeStyle
.pixelHeight
= parseInt(layoutWidth(element
) * element
.currentStyle
["ie7-height"].slice(0, -1) / 100);
1494 eval("var _fixHeight=" + rotate(_fixWidth
));
1496 // apply box-model + min/max fixes
1500 if (appVersion
< 7) {
1501 IE7
.CSS
.addRecalc("min-width", NUMERIC
, layout
.minWidth
);
1502 IE7
.CSS
.addFix(/\bmin-height\s*/, "height");
1506 // =========================================================================
1508 // =========================================================================
1510 // a small transparent image used as a placeholder
1511 var BLANK_GIF
= makePath("blank.gif", path
);
1513 var ALPHA_IMAGE_LOADER
= "DXImageTransform.Microsoft.AlphaImageLoader";
1514 var PNG_FILTER
= "progid:" + ALPHA_IMAGE_LOADER
+ "(src='%1',sizingMethod='%2')";
1516 // regular expression version of the above
1521 function fixImage(element
) {
1522 if (PNG
.test(element
.src
)) {
1523 // we have to preserve width and height
1524 var image
= new Image(element
.width
, element
.height
);
1525 image
.onload = function() {
1526 element
.width
= image
.width
;
1527 element
.height
= image
.height
;
1530 image
.src
= element
.src
;
1531 // store the original url (we'll put it back when it's printed)
1532 element
.pngSrc
= element
.src
;
1533 // add the AlphaImageLoader thingy
1538 if (appVersion
< 7) {
1540 // e.g. apply the hack to all files ending in ".png"
1541 // IE7_PNG_SUFFIX = ".png";
1542 // You can also set it to a RegExp
1543 // IE7_PNG_SUFFIX = /\d+\.png$/;
1545 // replace background(-image): url(..) .. with background(-image): .. ;filter: ..;
1546 IE7
.CSS
.addFix(/background(-image)?\s*:\s*([^};]*)?url\(([^\)]+)\)([^;}]*)?/, function(match
, $1, $2, url
, $4) {
1547 url
= getString(url
);
1548 return PNG
.test(url
) ? "filter:" + format(PNG_FILTER
, url
, $4.indexOf("no-repeat") === -1 ? "scale" : "crop") +
1549 ";zoom:1;background" + ($1||"") + ":" + ($2||"") + "none" + ($4||"") : match
;
1553 IE7
.CSS
.addRecalc(/list\-style(\-image)?/, "[^};]*url", function(element
) {
1554 var url
= element
.currentStyle
.listStyleImage
.slice(5, -2);
1555 if (PNG
.test(url
)) {
1556 if (element
.nodeName
=== "LI") {
1557 fixListStyleImage(element
, url
)
1558 } else if (element
.nodeName
=== "UL") {
1559 for (var i
= 0, li
; li
= element
.childNodes
[i
]; i
++) {
1560 if (li
.nodeName
=== "LI") fixListStyleImage(li
, url
);
1566 function fixListStyleImage(element
, src
) {
1567 var style
= element
.runtimeStyle
;
1568 var originalHeight
= element
.offsetHeight
;
1569 var image
= new Image
;
1570 image
.onload = function() {
1571 var paddingLeft
= element
.currentStyle
.paddingLeft
;
1572 paddingLeft
= paddingLeft
=== "0px" ? 0 : getPixelValue(element
, paddingLeft
);
1573 style
.paddingLeft
= (paddingLeft
+ this.width
) + "px";
1574 style
.marginLeft
= -this.width
+ "px";
1575 style
.listStyleType
= "none";
1576 style
.listStyleImage
= "none";
1577 style
.paddingTop
= Math
.max(originalHeight
- element
.offsetHeight
, 0) + "px";
1578 addFilter(element
, "crop", src
);
1579 element
.style
.zoom
= "100%";
1584 // -----------------------------------------------------------------------
1585 // fix PNG transparency (HTML images)
1586 // -----------------------------------------------------------------------
1588 IE7
.HTML
.addRecalc("img,input", function(element
) {
1589 if (element
.nodeName
=== "INPUT" && element
.type
!== "image") return;
1591 addEventHandler(element
, "onpropertychange", function() {
1592 if (!printing
&& event
.propertyName
=== "src" &&
1593 element
.src
.indexOf(BLANK_GIF
) === -1) fixImage(element
);
1597 // assume that background images should not be printed
1598 // (if they are not transparent then they'll just obscure content)
1599 // but we'll put foreground images back...
1600 var printing
= false;
1601 addEventHandler(window
, "onbeforeprint", function() {
1603 for (var i
= 0; i
< filtered
.length
; i
++) removeFilter(filtered
[i
]);
1605 addEventHandler(window
, "onafterprint", function() {
1606 for (var i
= 0; i
< filtered
.length
; i
++) addFilter(filtered
[i
]);
1612 function addFilter(element
, sizingMethod
, src
) {
1613 var filter
= element
.filters
[ALPHA_IMAGE_LOADER
];
1615 filter
.src
= src
|| element
.src
;
1616 filter
.enabled
= true;
1618 element
.runtimeStyle
.filter
= format(PNG_FILTER
, src
|| element
.src
, sizingMethod
|| "scale");
1619 filtered
.push(element
);
1621 // remove the real image
1622 element
.src
= BLANK_GIF
;
1625 function removeFilter(element
) {
1626 element
.src
= element
.pngSrc
;
1627 element
.filters
[ALPHA_IMAGE_LOADER
].enabled
= false;
1630 // =========================================================================
1632 // =========================================================================
1635 if (appVersion
>= 7) return;
1637 // some things to consider for this hack.
1638 // the document body requires a fixed background. even if
1639 // it is just a blank image.
1640 // you have to use setExpression instead of onscroll, this
1641 // together with a fixed body background helps avoid the
1642 // annoying screen flicker of other solutions.
1644 IE7
.CSS
.addRecalc("position", "fixed", _positionFixed
, "absolute");
1645 IE7
.CSS
.addRecalc("background(-attachment)?", "[^};]*fixed", _backgroundFixed
);
1647 // scrolling is relative to the documentElement (HTML tag) when in
1648 // standards mode, otherwise it's relative to the document body
1649 var $viewport
= MSIE5
? "body" : "documentElement";
1651 function _fixBackground() {
1652 // this is required by both position:fixed and background-attachment:fixed.
1653 // it is necessary for the document to also have a fixed background image.
1654 // we can fake this with a blank image if necessary
1655 if (body
.currentStyle
.backgroundAttachment
!== "fixed") {
1656 if (body
.currentStyle
.backgroundImage
=== "none") {
1657 body
.runtimeStyle
.backgroundRepeat
= "no-repeat";
1658 body
.runtimeStyle
.backgroundImage
= "url(" + BLANK_GIF
+ ")"; // dummy
1660 body
.runtimeStyle
.backgroundAttachment
= "fixed";
1662 _fixBackground
= Undefined
;
1665 var _tmp
= createTempElement("img");
1667 function _isFixed(element
) {
1668 return element
? isFixed(element
) || _isFixed(element
.parentElement
) : false;
1671 function _setExpression(element
, propertyName
, expression
) {
1672 setTimeout("document.all." + element
.uniqueID
+ ".runtimeStyle.setExpression('" + propertyName
+ "','" + expression
+ "')", 0);
1675 // -----------------------------------------------------------------------
1676 // backgroundAttachment: fixed
1677 // -----------------------------------------------------------------------
1679 function _backgroundFixed(element
) {
1680 if (register(_backgroundFixed
, element
, element
.currentStyle
.backgroundAttachment
=== "fixed" && !element
.contains(body
))) {
1682 util
.bgLeft(element
);
1683 util
.bgTop(element
);
1684 _backgroundPosition(element
);
1688 function _backgroundPosition(element
) {
1689 _tmp
.src
= element
.currentStyle
.backgroundImage
.slice(5, -2);
1690 var parentElement
= element
.canHaveChildren
? element
: element
.parentElement
;
1691 parentElement
.appendChild(_tmp
);
1692 util
.setOffsetLeft(element
);
1693 util
.setOffsetTop(element
);
1694 parentElement
.removeChild(_tmp
);
1697 // -----------------------------------------------------------------------
1699 // -----------------------------------------------------------------------
1701 function _positionFixed(element
) {
1702 if (register(_positionFixed
, element
, isFixed(element
))) {
1703 setOverrideStyle(element
, "position", "absolute");
1704 setOverrideStyle(element
, "left", element
.currentStyle
.left
);
1705 setOverrideStyle(element
, "top", element
.currentStyle
.top
);
1707 IE7
.Layout
.fixRight(element
);
1708 //IE7.Layout.fixBottom(element);
1709 _foregroundPosition(element
);
1713 function _foregroundPosition(element
, recalc
) {
1714 document
.body
.getBoundingClientRect(); // force a reflow
1715 util
.positionTop(element
, recalc
);
1716 util
.positionLeft(element
, recalc
, true);
1717 if (!element
.runtimeStyle
.autoLeft
&& element
.currentStyle
.marginLeft
=== "auto" &&
1718 element
.currentStyle
.right
!== "auto") {
1719 var left
= viewport
.clientWidth
- util
.getPixelWidth(element
, element
.currentStyle
.right
) -
1720 util
.getPixelWidth(element
, element
.runtimeStyle
._left
) - element
.clientWidth
;
1721 if (element
.currentStyle
.marginRight
=== "auto") left
= parseInt(left
/ 2);
1722 if (_isFixed(element
.offsetParent
)) element
.runtimeStyle
.pixelLeft
+= left
;
1723 else element
.runtimeStyle
.shiftLeft
= left
;
1725 if (!element
.runtimeStyle
.fixedWidth
) util
.clipWidth(element
);
1726 if (!element
.runtimeStyle
.fixedHeight
) util
.clipHeight(element
);
1729 // -----------------------------------------------------------------------
1730 // capture window resize
1731 // -----------------------------------------------------------------------
1733 function _resize() {
1734 // if the window has been resized then some positions need to be
1735 // recalculated (especially those aligned to "right" or "top"
1736 var elements
= _backgroundFixed
.elements
;
1737 for (var i
in elements
) _backgroundPosition(elements
[i
]);
1738 elements
= _positionFixed
.elements
;
1739 for (i
in elements
) {
1740 _foregroundPosition(elements
[i
], true);
1741 _foregroundPosition(elements
[i
], true);
1746 // use a timer (sometimes this is a good way to prevent resize loops)
1748 addResize(function() {
1749 if (!_timer
) _timer
= setTimeout(_resize
, 100);
1752 // -----------------------------------------------------------------------
1754 // -----------------------------------------------------------------------
1758 var _horizontal = function(util
) {
1759 util
.bgLeft = function(element
) {
1760 element
.style
.backgroundPositionX
= element
.currentStyle
.backgroundPositionX
;
1761 if (!_isFixed(element
)) {
1762 _setExpression(element
, "backgroundPositionX", "(parseInt(runtimeStyle.offsetLeft)+document." + $viewport
+ ".scrollLeft)||0");
1766 util
.setOffsetLeft = function(element
) {
1767 var propertyName
= _isFixed(element
) ? "backgroundPositionX" : "offsetLeft";
1768 element
.runtimeStyle
[propertyName
] =
1769 util
.getOffsetLeft(element
, element
.style
.backgroundPositionX
) -
1770 element
.getBoundingClientRect().left
- element
.clientLeft
+ 2;
1773 util
.getOffsetLeft = function(element
, position
) {
1780 return viewport
.clientWidth
- _tmp
.offsetWidth
;
1782 return (viewport
.clientWidth
- _tmp
.offsetWidth
) / 2;
1784 if (PERCENT
.test(position
)) {
1785 return parseInt((viewport
.clientWidth
- _tmp
.offsetWidth
) * parseFloat(position
) / 100);
1787 _tmp
.style
.left
= position
;
1788 return _tmp
.offsetLeft
;
1792 util
.clipWidth = function(element
) {
1793 var fixWidth
= element
.runtimeStyle
.fixWidth
;
1794 element
.runtimeStyle
.borderRightWidth
= "";
1795 element
.runtimeStyle
.width
= fixWidth
? util
.getPixelWidth(element
, fixWidth
) + "px" : "";
1796 if (element
.currentStyle
.width
!== "auto") {
1797 var rect
= element
.getBoundingClientRect();
1798 var width
= element
.offsetWidth
- viewport
.clientWidth
+ rect
.left
- 2;
1800 element
.runtimeStyle
.borderRightWidth
= "0px";
1801 width
= Math
.max(getPixelValue(element
, element
.currentStyle
.width
) - width
, 0);
1802 setOverrideStyle(element
, "width", width
);
1808 util
.positionLeft = function(element
, recalc
) {
1809 // if the element's width is in % units then it must be recalculated
1810 // with respect to the viewport
1811 if (!recalc
&& PERCENT
.test(element
.currentStyle
.width
)) {
1812 element
.runtimeStyle
.fixWidth
= element
.currentStyle
.width
;
1814 if (element
.runtimeStyle
.fixWidth
) {
1815 element
.runtimeStyle
.width
= util
.getPixelWidth(element
, element
.runtimeStyle
.fixWidth
);
1818 // // if the element is fixed on the right then no need to recalculate
1819 // if (!element.runtimeStyle.autoLeft) return;
1821 element
.runtimeStyle
.shiftLeft
= 0;
1822 element
.runtimeStyle
._left
= element
.currentStyle
.left
;
1823 // is the element fixed on the right?
1824 element
.runtimeStyle
.autoLeft
= element
.currentStyle
.right
!== "auto" && element
.currentStyle
.left
=== "auto";
1826 // reset the element's "left" value and get it's natural position
1827 element
.runtimeStyle
.left
= "";
1828 element
.runtimeStyle
.screenLeft
= util
.getScreenLeft(element
);
1829 element
.runtimeStyle
.pixelLeft
= element
.runtimeStyle
.screenLeft
;
1830 // if the element is contained by another fixed element then there is no need to
1831 // continually recalculate it's left position
1832 if (!recalc
&& !_isFixed(element
.offsetParent
)) {
1833 // onsrcoll produces jerky movement, so we use an expression
1834 _setExpression(element
, "pixelLeft", "runtimeStyle.screenLeft+runtimeStyle.shiftLeft+document." + $viewport
+ ".scrollLeft");
1838 // I've forgotten how this works...
1839 util
.getScreenLeft = function(element
) { // thanks to kevin newman (captainn)
1840 var screenLeft
= element
.offsetLeft
, nested
= 1;
1841 if (element
.runtimeStyle
.autoLeft
) {
1842 screenLeft
= viewport
.clientWidth
- element
.offsetWidth
- util
.getPixelWidth(element
, element
.currentStyle
.right
);
1844 // accommodate margins
1845 if (element
.currentStyle
.marginLeft
!== "auto") {
1846 screenLeft
-= util
.getPixelWidth(element
, element
.currentStyle
.marginLeft
);
1848 while (element
= element
.offsetParent
) {
1849 if (element
.currentStyle
.position
!== "static") nested
= -1;
1850 screenLeft
+= element
.offsetLeft
* nested
;
1855 util
.getPixelWidth = function(element
, value
) {
1856 return PERCENT
.test(value
) ? parseInt(parseFloat(value
) / 100 * viewport
.clientWidth
) : getPixelValue(element
, value
);
1859 eval("var _vertical=" + rotate(_horizontal
));
1864 // =========================================================================
1866 // =========================================================================
1868 /* ---------------------------------------------------------------------
1870 This module alters the structure of the document.
1871 It may adversely affect other CSS rules. Be warned.
1873 --------------------------------------------------------------------- */
1875 if (appVersion
< 7) {
1876 var WRAPPER_STYLE
= {
1877 backgroundColor
: "transparent",
1878 backgroundImage
: "none",
1879 backgroundPositionX
: null,
1880 backgroundPositionY
: null,
1881 backgroundRepeat
: null,
1883 borderRightWidth
: 0,
1884 borderBottomWidth
: 0,
1885 borderLeftStyle
: "none",
1886 borderTopStyle
: "none",
1887 borderRightStyle
: "none",
1888 borderBottomStyle
: "none",
1890 borderLeftColor
: "#000",
1891 borderTopColor
: "#000",
1892 borderRightColor
: "#000",
1893 borderBottomColor
: "#000",
1902 IE7
.CSS
.addRecalc("overflow", "visible", function(element
) {
1903 if (element
.currentStyle
.position
=== "absolute") return;
1905 // don't do this again
1906 if (element
.parentNode
.ie7_wrapped
) return;
1908 // if max-height is applied, makes sure it gets applied first
1909 if (IE7
.Layout
&& element
.currentStyle
["max-height"] !== "auto") {
1910 IE7
.Layout
.maxHeight(element
);
1913 if (element
.currentStyle
.marginLeft
=== "auto") element
.style
.marginLeft
= 0;
1914 if (element
.currentStyle
.marginRight
=== "auto") element
.style
.marginRight
= 0;
1916 var wrapper
= document
.createElement(ANON
);
1917 wrapper
.ie7_wrapped
= element
;
1918 for (var propertyName
in WRAPPER_STYLE
) {
1919 wrapper
.style
[propertyName
] = element
.currentStyle
[propertyName
];
1920 if (WRAPPER_STYLE
[propertyName
] != null) {
1921 element
.runtimeStyle
[propertyName
] = WRAPPER_STYLE
[propertyName
];
1924 wrapper
.style
.display
= "block";
1925 wrapper
.style
.position
= "relative";
1926 element
.runtimeStyle
.position
= "absolute";
1927 element
.parentNode
.insertBefore(wrapper
, element
);
1928 wrapper
.appendChild(element
);
1932 // =========================================================================
1934 // =========================================================================
1936 function ie7Quirks() {
1937 var FONT_SIZES
= "xx-small,x-small,small,medium,large,x-large,xx-large".split(",");
1938 for (var i
= 0; i
< FONT_SIZES
.length
; i
++) {
1939 FONT_SIZES
[FONT_SIZES
[i
]] = FONT_SIZES
[i
- 1] || "0.67em";
1942 IE7
.CSS
.addFix(/(font(-size)?\s*:\s*)([\w.-]+)/, function(match
, label
, size
, value
) {
1943 return label
+ (FONT_SIZES
[value
] || value
);
1946 var NEGATIVE
= /^\-/, LENGTH
= /(em|ex)$/i;
1947 var EM
= /em$/i, EX
= /ex$/i;
1949 getPixelValue = function(element
, value
) {
1950 if (PIXEL
.test(value
)) return parseInt(value
)||0;
1951 var scale
= NEGATIVE
.test(value
)? -1 : 1;
1952 if (LENGTH
.test(value
)) scale
*= getFontScale(element
);
1953 temp
.style
.width
= scale
< 0 ? value
.slice(1) : value
;
1954 body
.appendChild(temp
);
1955 // retrieve pixel width
1956 value
= scale
* temp
.offsetWidth
;
1957 // remove the temporary element
1959 return parseInt(value
);
1962 var temp
= createTempElement();
1963 function getFontScale(element
) {
1965 temp
.style
.fontFamily
= element
.currentStyle
.fontFamily
;
1966 temp
.style
.lineHeight
= element
.currentStyle
.lineHeight
;
1967 //temp.style.fontSize = "";
1968 while (element
!= body
) {
1969 var fontSize
= element
.currentStyle
["ie7-font-size"];
1971 if (EM
.test(fontSize
)) scale
*= parseFloat(fontSize
);
1972 else if (PERCENT
.test(fontSize
)) scale
*= (parseFloat(fontSize
) / 100);
1973 else if (EX
.test(fontSize
)) scale
*= (parseFloat(fontSize
) / 2);
1975 temp
.style
.fontSize
= fontSize
;
1979 element
= element
.parentElement
;
1984 // cursor:pointer (IE5.x)
1985 IE7
.CSS
.addFix(/cursor\s*:\s*pointer/, "cursor:hand");
1986 // display:list-item (IE5.x)
1987 IE7
.CSS
.addFix(/display\s*:\s*list-item/, "display:block");
1989 // -----------------------------------------------------------------------
1991 // -----------------------------------------------------------------------
1993 function fixMargin(element
) {
1994 var parent
= element
.parentElement
;
1995 var margin
= parent
.offsetWidth
- element
.offsetWidth
- getPaddingWidth(parent
);
1996 var autoRight
= (element
.currentStyle
["ie7-margin"] && element
.currentStyle
.marginRight
=== "auto") ||
1997 element
.currentStyle
["ie7-margin-right"] === "auto";
1998 switch (parent
.currentStyle
.textAlign
) {
2000 margin
= autoRight
? parseInt(margin
/ 2) : 0;
2001 element
.runtimeStyle
.marginRight
= margin
+ "px";
2004 if (autoRight
) margin
= 0;
2006 if (autoRight
) margin
/= 2;
2007 element
.runtimeStyle
.marginLeft
= parseInt(margin
) + "px";
2011 function getPaddingWidth(element
) {
2012 return getPixelValue(element
, element
.currentStyle
.paddingLeft
) +
2013 getPixelValue(element
, element
.currentStyle
.paddingRight
);
2016 IE7
.CSS
.addRecalc("margin(-left|-right)?", "[^};]*auto", function(element
) {
2017 if (register(fixMargin
, element
,
2018 element
.parentElement
&&
2019 element
.currentStyle
.display
=== "block" &&
2020 element
.currentStyle
.marginLeft
=== "auto" &&
2021 element
.currentStyle
.position
!== "absolute")) {
2026 addResize(function() {
2027 for (var i
in fixMargin
.elements
) {
2028 var element
= fixMargin
.elements
[i
];
2029 element
.runtimeStyle
.marginLeft
=
2030 element
.runtimeStyle
.marginRight
= "";
2037 // =========================================================================
2039 // =========================================================================
2041 var BRACKETS
= "\\([^)]+\\)";
2043 // pseudo-elements can be declared with a double colon
2044 encoder
.add(/::(before|after)/, ":$1");
2046 if (appVersion
< 8) {
2048 if (IE7
.CSS
.pseudoClasses
) IE7
.CSS
.pseudoClasses
+= "|";
2049 IE7
.CSS
.pseudoClasses
+= "before|after|lang" + BRACKETS
;
2051 // -----------------------------------------------------------------------
2052 // propertyName: inherit;
2053 // -----------------------------------------------------------------------
2055 function parseInherited(cssText
) {
2056 return cssText
.replace(new RegExp("([{;\\s])(" + inheritedProperties
.join("|") + ")\\s*:\\s*([^;}]+)", "g"), "$1$2:$3;ie7-$2:$3");
2059 var INHERITED
= /[\w-]+\s*:\s*inherit/g;
2060 var STRIP_IE7_FLAGS
= /ie7\-|\s*:\s*inherit/g;
2061 var DASH_LOWER
= /\-([a-z])/g;
2062 function toUpper(match
, chr
) {return chr
.toUpperCase()};
2064 IE7
.CSS
.addRecalc("[\\w-]+", "inherit", function(element
, cssText
) {
2065 if (element
.parentElement
) {
2066 var inherited
= cssText
.match(INHERITED
);
2067 for (var i
= 0; i
< inherited
.length
; i
++) {
2068 var propertyName
= inherited
[i
].replace(STRIP_IE7_FLAGS
, "");
2069 if (element
.currentStyle
["ie7-" + propertyName
] === "inherit") {
2070 propertyName
= propertyName
.replace(DASH_LOWER
, toUpper
);
2071 element
.runtimeStyle
[propertyName
] = element
.parentElement
.currentStyle
[propertyName
];
2075 }, function(match
) {
2076 inheritedProperties
.push(rescape(match
.slice(1).split(":")[0]));
2080 // -----------------------------------------------------------------------
2081 // dynamic pseudo-classes
2082 // -----------------------------------------------------------------------
2084 var Focus
= new DynamicPseudoClass("focus", function(element
) {
2085 var instance
= arguments
;
2087 IE7
.CSS
.addEventHandler(element
, "onfocus", function() {
2088 Focus
.unregister(instance
); // in case it starts with focus
2089 Focus
.register(instance
);
2092 IE7
.CSS
.addEventHandler(element
, "onblur", function() {
2093 Focus
.unregister(instance
);
2096 // check the active element for initial state
2097 if (element
== document
.activeElement
) {
2098 Focus
.register(instance
)
2102 var Active
= new DynamicPseudoClass("active", function(element
) {
2103 var instance
= arguments
;
2104 IE7
.CSS
.addEventHandler(element
, "onmousedown", function() {
2105 Active
.register(instance
);
2109 // globally trap the mouseup event (thanks Martijn!)
2110 addEventHandler(document
, "onmouseup", function() {
2111 var instances
= Active
.instances
;
2112 for (var i
in instances
) Active
.unregister(instances
[i
]);
2115 // -----------------------------------------------------------------------
2116 // IE7 pseudo elements
2117 // -----------------------------------------------------------------------
2120 var URL
= /^url\s*\(\s*([^)]*)\)$/;
2121 var POSITION_MAP
= {
2122 before0
: "beforeBegin",
2123 before1
: "afterBegin",
2128 var PseudoElement
= IE7
.PseudoElement
= Rule
.extend({
2129 constructor: function(selector
, position
, cssText
) {
2130 // initialise object properties
2131 this.position
= position
;
2132 var content
= cssText
.match(PseudoElement
.CONTENT
), match
, entity
;
2134 content
= content
[1];
2135 match
= content
.split(/\s+/);
2136 for (var i
= 0; (entity
= match
[i
]); i
++) {
2137 match
[i
] = /^attr/.test(entity
) ? {attr
: entity
.slice(5, -1)} :
2138 entity
.charAt(0) === "'" ? getString(entity
) : decode(entity
);
2142 this.content
= content
;
2143 // CSS text needs to be decoded immediately
2144 this.base(selector
, decode(cssText
));
2148 // execute the underlying css query for this class
2149 this.match
= cssQuery(this.selector
);
2150 for (var i
= 0; i
< this.match
.length
; i
++) {
2151 var runtimeStyle
= this.match
[i
].runtimeStyle
;
2152 if (!runtimeStyle
[this.position
]) runtimeStyle
[this.position
] = {cssText
:""};
2153 runtimeStyle
[this.position
].cssText
+= ";" + this.cssText
;
2154 if (this.content
!= null) runtimeStyle
[this.position
].content
= this.content
;
2158 create: function(target
) {
2159 var generated
= target
.runtimeStyle
[this.position
];
2161 // copy the array of values
2162 var content
= [].concat(generated
.content
|| "");
2163 for (var j
= 0; j
< content
.length
; j
++) {
2164 if (typeof content
[j
] == "object") {
2165 content
[j
] = target
.getAttribute(content
[j
].attr
);
2168 content
= content
.join("");
2169 var url
= content
.match(URL
);
2170 var cssText
= "overflow:hidden;" + generated
.cssText
.replace(/'/g, '"');
2171 var position = POSITION_MAP[this.position + Number(target.canHaveChildren)];
2172 var id = 'ie7_pseudo' + PseudoElement.count++;
2173 target.insertAdjacentHTML(position, format(PseudoElement.ANON, this.className, id, cssText, url ? "" : content));
2175 var src = getString(url[1]);
2176 var pseudoElement = document.getElementById(id);
2177 pseudoElement.src = src;
2178 addFilter(pseudoElement, "crop
");
2179 var targetIsFloated = target.currentStyle.styleFloat !== "none
";
2180 if (pseudoElement.currentStyle.display === "inline
" || targetIsFloated) {
2181 if (appVersion < 7 && targetIsFloated && target.canHaveChildren) {
2182 target.runtimeStyle.display = "inline
";
2183 target.runtimeStyle.position = "relative
";
2184 pseudoElement.runtimeStyle.position = "absolute
";
2186 pseudoElement.style.display = "inline
-block
";
2187 if (target.currentStyle.styleFloat !== "none
") {
2188 pseudoElement.style.pixelWidth = target.offsetWidth;
2190 var image = new Image;
2191 image.onload = function() {
2192 pseudoElement.style.pixelWidth = this.width;
2193 pseudoElement.style.pixelHeight = Math.max(this.height, pseudoElement.offsetHeight);
2198 target.runtimeStyle[this.position] = null;
2202 recalc: function() {
2203 if (this.content == null) return;
2204 for (var i = 0; i < this.match.length; i++) {
2205 this.create(this.match[i]);
2209 toString: function() {
2210 return "." + this.className + "{display
:inline
}";
2213 CONTENT: /content\s*:\s*([^;]*)(;|$)/,
2214 ANON: "<ie7
:! class='ie7_anon %1' id
=%2 style
='%3'>%4</ie7
:!>",
2215 MATCH: /(.*):(before|after).*/,
2220 IE7._getLang = function(element) {
2222 while (element && element.nodeType === 1) {
2223 lang = element.lang || element.getAttribute("lang
") || "";
2225 element = element.parentNode;
2230 FILTER = extend(FILTER, {
2231 ":lang
\\(([^)]+)\\)": "((ii
=IE7
._getLang(e
))==='$1'||ii
.indexOf('$1-')===0)&&"
2235 // =========================================================================
2237 // =========================================================================
2239 var UNSUCCESSFUL = /^(submit|reset|button)$/;
2241 // -----------------------------------------------------------------------
2243 // -----------------------------------------------------------------------
2245 // IE bug means that innerText is submitted instead of "value
"
2246 IE7.HTML.addRecalc("button
,input
", function(button) {
2247 if (button.nodeName === "BUTTON
") {
2248 var match = button.outerHTML.match(/ value="([^"]*)"/i
);
2249 button
.runtimeStyle
.value
= match
? match
[1] : "";
2251 // flag the button/input that was used to submit the form
2252 if (button
.type
=== "submit") {
2253 addEventHandler(button
, "onclick", function() {
2254 button
.runtimeStyle
.clicked
= true;
2255 setTimeout("document.all." + button
.uniqueID
+ ".runtimeStyle.clicked=false", 1);
2260 // -----------------------------------------------------------------------
2262 // -----------------------------------------------------------------------
2264 // only submit "successful controls
2265 IE7
.HTML
.addRecalc("form", function(form
) {
2266 addEventHandler(form
, "onsubmit", function() {
2267 for (var element
, i
= 0; element
= form
[i
]; i
++) {
2268 if (UNSUCCESSFUL
.test(element
.type
) && !element
.disabled
&& !element
.runtimeStyle
.clicked
) {
2269 element
.disabled
= true;
2270 setTimeout("document.all." + element
.uniqueID
+ ".disabled=false", 1);
2271 } else if (element
.nodeName
=== "BUTTON" && element
.type
=== "submit") {
2272 setTimeout("document.all." + element
.uniqueID
+ ".value='" + element
.value
+ "'", 1);
2273 element
.value
= element
.runtimeStyle
.value
;
2279 // -----------------------------------------------------------------------
2281 // -----------------------------------------------------------------------
2283 // get rid of the spurious tooltip produced by the alt attribute on images
2284 IE7
.HTML
.addRecalc("img", function(img
) {
2285 if (img
.alt
&& !img
.title
) img
.title
= "";
2288 // =========================================================================
2290 // =========================================================================
2292 if (appVersion
< 8) {
2293 IE7
.CSS
.addRecalc("border-spacing", NUMERIC
, function(element
) {
2294 if (element
.currentStyle
.borderCollapse
!== "collapse") {
2295 element
.cellSpacing
= getPixelValue(element
, element
.currentStyle
["ie7-border-spacing"].split(" ")[0]);
2298 IE7
.CSS
.addRecalc("box-sizing", "content-box", IE7
.Layout
.boxSizing
);
2299 IE7
.CSS
.addRecalc("box-sizing", "border-box", IE7
.Layout
.borderBox
);
2302 // =========================================================================
2304 // =========================================================================
2306 if (appVersion
< 8) {
2307 // fix object[type=image/*]
2308 var IMAGE
= /^image/i;
2309 IE7
.HTML
.addRecalc("object", function(element
) {
2310 if (IMAGE
.test(element
.type
)) {
2311 element
.body
.style
.cssText
= "margin:0;padding:0;border:none;overflow:hidden";
2317 // =========================================================================
2319 // =========================================================================
2321 var NOT_NEXT_BY_TYPE
= "!IE7._getElementSiblingByType(e,'next')&&",
2322 NOT_PREVIOUS_BY_TYPE
= NOT_NEXT_BY_TYPE
.replace("next", "previous");
2324 if (IE7
.CSS
.pseudoClasses
) IE7
.CSS
.pseudoClasses
+= "|";
2325 IE7
.CSS
.pseudoClasses
+= "(?:first|last|only)\\-(?:child|of\\-type)|empty|root|target|" +
2326 ("not|nth\\-child|nth\\-last\\-child|nth\\-of\\-type|nth\\-last\\-of\\-type".split("|").join(BRACKETS
+ "|") + BRACKETS
);
2329 var Checked
= new DynamicPseudoClass("checked", function(element
) {
2330 if (typeof element
.checked
!== "boolean") return;
2331 var instance
= arguments
;
2332 IE7
.CSS
.addEventHandler(element
, "onpropertychange", function() {
2333 if (event
.propertyName
=== "checked") {
2334 if (element
.checked
=== true) Checked
.register(instance
);
2335 else Checked
.unregister(instance
);
2338 // check current checked state
2339 if (element
.checked
=== true) Checked
.register(instance
);
2343 var Enabled
= new DynamicPseudoClass("enabled", function(element
) {
2344 if (typeof element
.disabled
!== "boolean") return;
2345 var instance
= arguments
;
2346 IE7
.CSS
.addEventHandler(element
, "onpropertychange", function() {
2347 if (event
.propertyName
=== "disabled") {
2348 if (element
.disabled
=== false) Enabled
.register(instance
);
2349 else Enabled
.unregister(instance
);
2352 // check current disabled state
2353 if (element
.disabled
=== false) Enabled
.register(instance
);
2357 var Disabled
= new DynamicPseudoClass("disabled", function(element
) {
2358 if (typeof element
.disabled
!== "boolean") return;
2359 var instance
= arguments
;
2360 IE7
.CSS
.addEventHandler(element
, "onpropertychange", function() {
2361 if (event
.propertyName
=== "disabled") {
2362 if (element
.disabled
=== true) Disabled
.register(instance
);
2363 else Disabled
.unregister(instance
);
2366 // check current disabled state
2367 if (element
.disabled
=== true) Disabled
.register(instance
);
2370 // :indeterminate (Kevin Newman)
2371 var Indeterminate
= new DynamicPseudoClass("indeterminate", function(element
) {
2372 if (typeof element
.indeterminate
!== "boolean") return;
2373 var instance
= arguments
;
2374 IE7
.CSS
.addEventHandler(element
, "onpropertychange", function() {
2375 if (event
.propertyName
=== "indeterminate") {
2376 if (element
.indeterminate
=== true) Indeterminate
.register(instance
);
2377 else Indeterminate
.unregister(instance
);
2380 IE7
.CSS
.addEventHandler(element
, "onclick", function() {
2381 Indeterminate
.unregister(instance
);
2383 // clever Kev says no need to check this up front
2387 var Target
= new DynamicPseudoClass("target", function(element
) {
2388 var instance
= arguments
;
2389 // if an element has a tabIndex then it can become "active".
2390 // The default is zero anyway but it works...
2391 if (!element
.tabIndex
) element
.tabIndex
= 0;
2392 // this doesn't detect the back button. I don't know how to do that without adding an iframe :-(
2393 IE7
.CSS
.addEventHandler(document
, "onpropertychange", function() {
2394 if (event
.propertyName
=== "activeElement") {
2395 if (element
.id
&& element
.id
=== location
.hash
.slice(1)) Target
.register(instance
);
2396 else Target
.unregister(instance
);
2399 // check the current location
2400 if (element
.id
&& element
.id
=== location
.hash
.slice(1)) Target
.register(instance
);
2403 // Register a node and index its siblings.
2404 var _currentIndex
= 1, // -@DRE
2405 allIndexes
= {_currentIndex
: 1};
2407 IE7
._indexOf = function(element
, last
, ofType
) {
2408 var parent
= element
.parentNode
;
2409 if (!parent
|| parent
.nodeType
!== 1) return NaN
;
2411 var tagName
= ofType
? element
.nodeName
: "";
2412 if (tagName
=== "TR" && element
.sectionRowIndex
>= 0) {
2413 var index
= element
.sectionRowIndex
;
2414 return last
? element
.parentNode
.rows
.length
- index
+ 1 : index
;
2416 if ((tagName
=== "TD" || tagName
=== "TH") && element
.cellIndex
>= 0) {
2417 index
= element
.cellIndex
;
2418 return last
? element
.parentNode
.cells
.length
- index
+ 1 : index
;
2420 if (allIndexes
._currentIndex
!== _currentIndex
) {
2421 allIndexes
= {_currentIndex
: _currentIndex
};
2423 var id
= (parent
.uniqueID
) + "-" + tagName
,
2424 indexes
= allIndexes
[id
];
2428 child
= parent
.firstChild
;
2430 if (ofType
? child
.nodeName
=== tagName
: child
.nodeName
> "@") {
2431 indexes
[child
.uniqueID
] = ++index
;
2433 child
= child
.nextSibling
;
2435 indexes
.length
= index
;
2436 allIndexes
[id
] = indexes
;
2438 index
= indexes
[element
.uniqueID
];
2439 return last
? indexes
.length
- index
+ 1 : index
;
2442 IE7
._isEmpty = function(node
) {
2443 node
= node
.firstChild
;
2445 if (node
.nodeType
=== 3 || node
.nodeName
> "@") return false;
2446 node
= node
.nextSibling
;
2451 IE7
._getElementSiblingByType = function(node
, direction
) {
2452 var tagName
= node
.nodeName
;
2453 direction
+= "Sibling";
2455 node
= node
[direction
];
2456 if (node
&& node
.nodeName
=== tagName
) break;
2461 var ONE
= {"+": 1, "-": -1}, SPACES
= / /g
;
2463 FILTER
= extend(extend({
2464 ":nth(-last)?-(?:child|(of-type))\\((<#nth_arg>)\\)(<#filter>)?": function(match
, last
, ofType
, args
, filters
) { // :nth- pseudo classes
2465 args
= args
.replace(SPACES
, "");
2467 var index
= "IE7._indexOf(e," + !!last
+ "," + !!ofType
+ ")";
2469 if (args
=== "even") args
= "2n";
2470 else if (args
=== "odd") args
= "2n+1";
2471 else if (!isNaN(args
)) args
= "0n" + ~~args
;
2473 args
= args
.split("n");
2474 var a
= ~~(ONE
[args
[0]] || args
[0] || 1),
2477 var expr
= index
+ "===" + b
;
2479 expr
= "((ii=" + index
+ ")-(" + b
+ "))%" + a
+ "===0&&ii" + (a
< 0 ? "<" : ">") + "=" + b
;
2481 return this.parse(filters
) + expr
+ "&&";
2484 "<#negation>": function(match
, simple
) {
2485 if (/:not/i.test(simple
)) throwSelectorError();
2487 if (/^[#.:\[]/.test(simple
)) {
2488 simple
= "*" + simple
;
2490 return "!(" + MATCHER
.parse(simple
).slice(3, -2) + ")&&";
2493 ":checked": "e.checked===true&&",
2494 ":disabled": "e.disabled===true&&",
2495 ":enabled": "e.disabled===false&&",
2496 ":last-child": "!" + NEXT_SIBLING
+ "&&",
2497 ":only-child": "!" + PREVIOUS_SIBLING
+ "&&!" + NEXT_SIBLING
+ "&&",
2498 ":first-of-type": NOT_PREVIOUS_BY_TYPE
,
2499 ":last-of-type": NOT_NEXT_BY_TYPE
,
2500 ":only-of-type": NOT_PREVIOUS_BY_TYPE
+ NOT_NEXT_BY_TYPE
,
2502 ":empty": "IE7._isEmpty(e)&&",
2504 ":target": "H&&" + ID_ATTRIBUTE
+ "===H&&"
2507 // =========================================================================
2509 // =========================================================================
2511 // =========================================================================
2513 // =========================================================================
2515 if (appVersion
=== 8) {
2516 IE7
.CSS
.addFix(/\bopacity\s*:/, "-ms-opacity:");
2518 IE7
.CSS
.addFix(/\bopacity\s*:\s*([\d.]+)/, function(match
, value
) {
2519 return "zoom:1;filter:Alpha(opacity=" + ((value
* 100) || 1) + ")";
2525 var cssQuery
= (function() {
2526 var CONTEXT
= /^[>+~]/;
2528 var useContext
= false;
2530 // This is not a selector engine in the strictest sense. So it's best to silently error.
2531 function cssQuery(selector
, context
, single
) {
2532 selector
= trim(selector
);
2533 if (!context
) context
= document
;
2535 useContext
= CONTEXT
.test(selector
);
2537 context
= context
.parentNode
;
2538 selector
= "*" + selector
;
2541 return selectQuery
.create(selector
, useContext
)(context
, single
? null : [], ref
);
2543 return single
? null : [];
2547 var VALID_SELECTOR
= /^(\\.|[' >+~#.\[\]:*(),\w-\^|$=]|[^\x00-\xa0])+$/;
2549 var _EVALUATED
= /^(href|src)$/;
2551 "class": "className",
2555 var IE7_CLASS_NAMES
= /\sie7_\w+/g;
2557 var USE_IFLAG
= /^(action|cite|codebase|data|dynsrc|href|longdesc|lowsrc|src|usemap|url)$/i;
2559 IE7
._getAttribute = function(element
, name
) {
2560 if (element
.getAttributeNode
) {
2561 var attribute
= element
.getAttributeNode(name
);
2563 name
= _ATTRIBUTES
[name
.toLowerCase()] || name
;
2564 if (!attribute
) attribute
= element
.attributes
[name
];
2565 var specified
= attribute
&& attribute
.specified
;
2567 if (element
[name
] && typeof element
[name
] == "boolean") return name
.toLowerCase();
2568 if ((specified
&& USE_IFLAG
.test(name
)) || (!attribute
&& MSIE5
) || name
=== "value" || name
=== "type") {
2569 return element
.getAttribute(name
, 2);
2571 if (name
=== "style") return element
.style
.cssText
.toLowerCase() || null;
2573 return specified
? String(attribute
.nodeValue
) : null;
2576 var names
= "colSpan,rowSpan,vAlign,dateTime,accessKey,tabIndex,encType,maxLength,readOnly,longDesc";
2577 // Convert the list of strings to a hash, mapping the lowercase name to the camelCase name.
2578 extend(_ATTRIBUTES
, combine(names
.toLowerCase().split(","), names
.split(",")));
2580 IE7
._getElementSibling = function(node
, direction
) {
2581 direction
+= "Sibling";
2583 node
= node
[direction
];
2584 if (node
&& node
.nodeName
> "@") break;
2589 var IMPLIED_ASTERISK
= /(^|[, >+~])([#.:\[])/g,
2593 HEX_ESCAPE
= /\\([\da-f]{2,2})/gi,
2594 LAST_CHILD
= /last/i;
2596 IE7
._byId = function(document
, id
) {
2597 var result
= document
.all
[id
] || null;
2598 // Returns a single element or a collection.
2599 if (!result
|| (result
.nodeType
&& IE7
._getAttribute(result
, "id") === id
)) return result
;
2600 // document.all has returned a collection of elements with name/id
2601 for (var i
= 0; i
< result
.length
; i
++) {
2602 if (IE7
._getAttribute(result
[i
], "id") === id
) return result
[i
];
2607 // =========================================================================
2608 // dom/selectors-api/CSSSelectorParser.js
2609 // =========================================================================
2611 // http://www.w3.org/TR/css3-selectors/#w3cselgrammar (kinda)
2612 var CSSSelectorParser
= RegGrp
.extend({
2613 dictionary
: new Dictionary({
2614 ident
: /\-?(\\.|[_a-z]|[^\x00-\xa0])(\\.|[\w-]|[^\x00-\xa0])*/,
2615 combinator
: /[\s>+~]/,
2616 operator
: /[\^~|$*]?=/,
2617 nth_arg
: /[+-]?\d+|[+-]?\d*n(?:\s*[+-]\s*\d+)?|even|odd/,
2620 'class': /\.(<#ident>)/,
2621 pseudo
: /\:([\w-]+)(?:\(([^)]+)\))?/,
2622 attr
: /\[(<#ident>)(?:(<#operator>)((?:\\.|[^\[\]#.:])+))?\]/,
2623 negation
: /:not\((<#tag>|<#id>|<#class>|<#attr>|<#pseudo>)\)/,
2624 sequence
: /(\\.|[~*]=|\+\d|\+?\d*n\s*\+\s*\d|[^\s>+~,\*])+/,
2625 filter
: /[#.:\[]<#sequence>/,
2626 selector
: /[^>+~](\\.|[^,])*?/,
2627 grammar
: /^(<#selector>)((,<#selector>)*)$/
2633 var normalizer
= new CSSSelectorParser({
2634 "\\\\.|[~*]\\s+=|\\+\\s+\\d": RegGrp
.IGNORE
,
2639 "\\s*([,>+~]|<#operator>)\\s*": "$1",
2644 function normalize(selector
) {
2645 selector
= normalizer
.parse(selector
.replace(HEX_ESCAPE
, "\\x$1"))
2646 .replace(UNESCAPE
, "$1")
2647 .replace(IMPLIED_ASTERISK
, "$1*$2");
2648 if (!VALID_SELECTOR
.test(selector
)) throwSelectorError();
2652 function unescape(query
) {
2653 // put string values back
2654 return query
.replace(ESCAPED
, unescapeString
);
2657 function unescapeString(match
, index
) {
2658 return strings
[index
];
2661 var BRACES
= /\{/g, BRACES_ESCAPED
= /\\{/g;
2663 function closeBlock(group
) {
2664 return Array((group
.replace(BRACES_ESCAPED
, "").match(BRACES
) || "").length
+ 1).join("}");
2667 FILTER
= new CSSSelectorParser(FILTER
);
2669 var TARGET
= /:target/i, ROOT
= /:root/i;
2671 function getConstants(selector
) {
2673 if (ROOT
.test(selector
)) constants
+= ",R=d.documentElement";
2674 if (TARGET
.test(selector
)) constants
+= ",H=d.location;H=H&&H.hash.replace('#','')";
2675 if (constants
|| selector
.indexOf("#") !== -1) {
2676 constants
= ",t=c.nodeType,d=t===9?c:c.ownerDocument||(c.document||c).parentWindow.document" + constants
;
2678 return "var ii" + constants
+ ";";
2682 " ": ";while(e!=s&&(e=e.parentNode)&&e.nodeType===1){",
2683 ">": ".parentElement;if(e){",
2684 "+": ";while((e=e.previousSibling)&&!(" + IS_ELEMENT
+ "))continue;if(e){",
2685 "~": ";while((e=e.previousSibling)){" + IF_ELEMENT
2688 var TOKEN
= /\be\b/g;
2690 MATCHER
= new CSSSelectorParser({
2691 "(?:(<#selector>)(<#combinator>))?(<#tag>)(<#filter>)?$": function(match
, before
, combinator
, tag
, filters
) {
2694 var TAG
= tag
.toUpperCase();
2695 group
+= "if(e.nodeName==='" + TAG
+ (TAG
=== tag
? "" : "'||e.nodeName==='" + tag
) + "'){";
2698 group
+= "if(" + FILTER
.parse(filters
).slice(0, -2) + "){";
2700 group
= group
.replace(TOKEN
, "e" + this.index
);
2702 group
+= "var e=e" + (this.index
++) + COMBINATOR
[combinator
];
2703 group
= group
.replace(TOKEN
, "e" + this.index
);
2706 group
+= this.parse(before
);
2712 var BY_ID
= "e0=IE7._byId(d,'%1');if(e0){",
2713 BY_TAG_NAME
= "var n=c.getElementsByTagName('%1');",
2714 STORE
= "if(r==null)return e0;r[k++]=e0;";
2718 var SELECTOR
= new CSSSelectorParser({
2719 "^((?:<#selector>)?(?:<#combinator>))(<#tag>)(<#filter>)?$": true
2724 var selectById
= new CSSSelectorParser({
2725 "^(<#tag>)#(<#ident>)(<#filter>)?( [^,]*)?$": function(match
, tagName
, id
, filters
, after
) {
2726 var block
= format(BY_ID
, id
), endBlock
= "}";
2728 block
+= MATCHER
.parse(tagName
+ filters
);
2729 endBlock
= closeBlock(block
);
2732 block
+= "s=c=e0;" + selectQuery
.parse("*" + after
);
2736 return block
+ endBlock
;
2739 "^([^#,]+)#(<#ident>)(<#filter>)?$": function(match
, before
, id
, filters
) {
2740 var block
= format(BY_ID
, id
);
2741 if (before
=== "*") {
2744 block
+= MATCHER
.parse(before
+ filters
) + STORE
+ "break";
2746 return block
+ closeBlock(block
);
2752 var selectQuery
= new CSSSelectorParser({
2753 "<#grammar>": function(match
, selector
, remainingSelectors
) {
2754 if (!this.groups
) this.groups
= [];
2756 var group
= SELECTOR
.exec(" " + selector
);
2758 if (!group
) throwSelectorError();
2760 this.groups
.push(group
.slice(1));
2762 if (remainingSelectors
) {
2763 return this.parse(remainingSelectors
.replace(COMMA
, ""));
2766 var groups
= this.groups
,
2767 tagName
= groups
[0][TAG_NAME
]; // first tag name
2769 for (var i
= 1; group
= groups
[i
]; i
++) { // search tag names
2770 if (tagName
!== group
[TAG_NAME
]) {
2771 tagName
= "*"; // mixed tag names, so use "*"
2776 var matcher
= "", store
= STORE
+ "continue filtering;";
2778 for (var i
= 0; group
= groups
[i
]; i
++) {
2780 if (tagName
!== "*") group
[TAG_NAME
] = "*"; // we are already filtering by tagName
2781 group
= group
.join("");
2782 if (group
=== " *") { // select all
2786 group
= MATCHER
.parse(group
);
2787 if (useContext
) group
+= "if(e" + MATCHER
.index
+ "==s){";
2788 matcher
+= group
+ store
+ closeBlock(group
);
2792 // reduce to a single loop
2793 var isWild
= tagName
=== "*";
2794 return (isWild
? "var n=c.all;" : format(BY_TAG_NAME
, tagName
)) +
2795 "filtering:while((e0=n[i++]))" +
2796 (isWild
? IF_ELEMENT
.replace(TOKEN
, "e0") : "{") +
2801 "^.*$": throwSelectorError
2804 var REDUNDANT_NODETYPE_CHECKS
= /\&\&(e\d+)\.nodeType===1(\)\{\s*if\(\1\.nodeName=)/g;
2806 selectQuery
.create = function(selector
) {
2807 if (!cache
[selector
]) {
2808 selector
= normalize(selector
);
2811 var block
= this.parse(selector
);
2814 if (selector
.indexOf("#") !== -1) {
2815 var byId
= selectById
.parse(selector
);
2818 "if(t===1||t===11|!c.getElementById){" +
2825 // remove redundant nodeType==1 checks
2826 block
= block
.replace(REDUNDANT_NODETYPE_CHECKS
, "$2");
2827 block
= getConstants(selector
) + decode(block
);
2828 cache
[selector
] = new Function("return function(c,r,s){var i=0,k=0,e0;" + block
+ "return r}")();
2830 return cache
[selector
];
2836 function throwSelectorError() {
2837 throw new SyntaxError("Invalid selector.");
2840 // -----------------------------------------------------------------------
2842 // -----------------------------------------------------------------------
2848 // http://javascript.nwbox.com/IEContentLoaded/
2849 if (!document
.body
) throw "continue";
2850 documentElement
.doScroll("left");
2852 setTimeout(arguments
.callee
, 1);
2855 // execute the inner text of the IE7 script
2857 eval(script
.innerHTML
);
2861 if (typeof IE7_PNG_SUFFIX
== "object") {
2862 PNG
= IE7_PNG_SUFFIX
;
2864 PNG
= new RegExp(rescape(window
.IE7_PNG_SUFFIX
|| "-trans.png") + "(\\?.*)?$", "i");
2867 // frequently used references
2868 body
= document
.body
;
2869 viewport
= MSIE5
? body
: documentElement
;
2872 body
.className
+= " ie7_body";
2873 documentElement
.className
+= " ie7_html";
2875 if (MSIE5
) ie7Quirks();