Dotclear

source: admin/js/ie7/IE9.js @ 1456:fc9436ce038f

Revision 1456:fc9436ce038f, 97.2 KB checked in by franck <carnet.franck.paul@…>, 12 years ago (diff)

Switch to IE9.js - See  http://code.google.com/p/ie7-js/

Line 
1/*
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
5*/
6
7/* W3C compliance for Microsoft Internet Explorer */
8
9/* credits/thanks:
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,
17  Ingo Chao
18*/
19
20// timestamp: Fri, 30 Apr 2010 20:59:18
21
22(function(window, document) {
23
24var IE7 = window.IE7 = {
25  version: "2.1(beta4)",
26  toString: K("[IE7]")
27};
28IE7.compat = 9;
29var appVersion = IE7.appVersion = navigator.appVersion.match(/MSIE (\d\.\d)/)[1] - 0;
30
31if (/ie7_off/.test(top.location.search) || appVersion < 5.5 || appVersion >= IE7.compat) return;
32
33var MSIE5 = appVersion < 6;
34
35var Undefined = K();
36var documentElement = document.documentElement, body, viewport;
37var ANON = "!";
38var HEADER = ":link{ie7-link:link}:visited{ie7-link:visited}";
39
40// -----------------------------------------------------------------------
41// external
42// -----------------------------------------------------------------------
43
44var RELATIVE = /^[\w\.]+[^:]*$/;
45function makePath(href, path) {
46  if (RELATIVE.test(href)) href = (path || "") + href;
47  return href;
48};
49
50function getPath(href, path) {
51  href = makePath(href, path);
52  return href.slice(0, href.lastIndexOf("/") + 1);
53};
54
55// Get the path to this script
56var script = document.scripts[document.scripts.length - 1];
57var path = getPath(script.src);
58
59// Use microsoft's http request object to load external files
60try {
61  var httpRequest = new ActiveXObject("Microsoft.XMLHTTP");
62} catch (ex) {
63  // ActiveX disabled
64}
65
66var fileCache = {};
67function loadFile(href, path) {
68  try {
69    href = makePath(href, path);
70    if (!fileCache[href]) {
71      httpRequest.open("GET", href, false);
72      httpRequest.send();
73      if (httpRequest.status == 0 || httpRequest.status == 200) {
74        fileCache[href] = httpRequest.responseText;
75      }
76    }
77  } catch (ex) {
78    // ignore errors
79  }
80  return fileCache[href] || "";
81};
82
83// -----------------------------------------------------------------------
84// OO support
85// -----------------------------------------------------------------------
86
87
88// This is a cut-down version of base2 (http://code.google.com/p/base2/)
89
90var _slice = Array.prototype.slice;
91
92// private
93var _FORMAT = /%([1-9])/g;
94var _LTRIM = /^\s\s*/;
95var _RTRIM = /\s\s*$/;
96var _RESCAPE = /([\/()[\]{}|*+-.,^$?\\])/g;           // safe regular expressions
97var _BASE = /\bbase\b/;
98var _HIDDEN = ["constructor", "toString"];            // only override these when prototyping
99
100var prototyping;
101
102function Base(){};
103Base.extend = function(_instance, _static) {
104  // Build the prototype.
105  prototyping = true;
106  var _prototype = new this;
107  extend(_prototype, _instance);
108  prototyping = false;
109
110  // Create the wrapper for the constructor function.
111  var _constructor = _prototype.constructor;
112  function klass() {
113    // Don't call the constructor function when prototyping.
114    if (!prototyping) _constructor.apply(this, arguments);
115  };
116  _prototype.constructor = klass;
117
118  // Build the static interface.
119  klass.extend = arguments.callee;
120  extend(klass, _static);
121  klass.prototype = _prototype;
122  return klass;
123};
124Base.prototype.extend = function(source) {
125  return extend(this, source);
126};
127
128
129// A collection of regular expressions and their associated replacement values.
130// A Base class for creating parsers.
131
132var HASH     = "#";
133var ITEMS    = "#";
134var KEYS     = ".";
135var COMPILED = "/";
136
137var 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;
145
146var RegGrp = Base.extend({
147  constructor: function(values) {
148    this[KEYS] = [];
149    this[ITEMS] = {};
150    this.merge(values);
151  },
152
153  //dictionary: null,
154  //ignoreCase: false,
155
156  add: function(expression, replacement) {
157    delete this[COMPILED];
158    if (expression instanceof RegExp) {
159      expression = expression.source;
160    }
161    if (!this[HASH + expression]) this[KEYS].push(String(expression));
162    return this[ITEMS][HASH + expression] = new RegGrp.Item(expression, replacement, this);
163  },
164
165  compile: function(recompile) {
166    if (recompile || !this[COMPILED]) {
167      this[COMPILED] = new RegExp(this, this.ignoreCase ? "gi" : "g");
168    }
169    return this[COMPILED];
170  },
171
172  merge: function(values) {
173    for (var i in values) this.add(i, values[i]);
174  },
175
176  exec: function(string) {
177    var group = this,
178        patterns = group[KEYS],
179        items = group[ITEMS], item;
180    var result = this.compile(true).exec(string);
181    if (result) {
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);
189          } else {
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};
193            return args;
194          }
195        }
196        offset = next;
197      }
198    }
199    return null;
200  },
201
202  parse: function(string) {
203    string += ""; // type safe
204    var group = this,
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) {
216            case "function":
217              return replacement.apply(group, args.slice(offset, next));
218            case "number":
219              return args[offset + replacement];
220            default:
221              return replacement;
222          }
223        }
224        offset = next;
225      }
226      return match;
227    });
228  },
229
230  toString: function() {
231    var strings = [],
232        keys = this[KEYS],
233        items = this[ITEMS], item;
234    for (var i = 0; item = items[HASH + keys[i]]; i++) {
235      strings[i] = item.source;
236    }
237    return "(" + strings.join(")|(") + ")";
238  }
239}, {
240  IGNORE: null, // a null replacement value means that there is no replacement.
241
242  Item: Base.extend({
243    constructor: function(source, replacement, owner) {
244      var length = source.indexOf("(") === -1 ? 0 : RegGrp.count(source);
245
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;
252        } else {
253          source = dictionary.parse(source);
254        }
255      }
256
257      if (typeof replacement == "number") replacement = String(replacement);
258      else if (replacement == null) replacement = 0;
259
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;
266        } else {
267          // A complicated lookup (e.g. "Hello $2 $1.").
268          var lookup = replacement, regexp;
269          replacement = function(match) {
270            if (!regexp) {
271              regexp = new RegExp(source, "g" + (this.ignoreCase ? "i": ""));
272            }
273            return match.replace(regexp, lookup);
274          };
275        }
276      }
277
278      this.length = length;
279      this.source = String(source);
280      this.replacement = replacement;
281    }
282  }),
283
284  count: function(expression) {
285    return (String(expression).replace(REGGRP_ESCAPE_COUNT, "").match(REGGRP_PAREN) || "").length;
286  }
287});
288
289var 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;
296    });
297  },
298
299  add: function(expression, replacement) {
300    // Get the underlying replacement value.
301    if (replacement instanceof RegExp) {
302      replacement = replacement.source;
303    }
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);
309    }
310    if (replacement.indexOf("<#") !== -1) {
311      replacement = this.parse(replacement);
312      nonCapturing = this.parse(nonCapturing);
313    }
314    var item = this.base(expression, replacement);
315    item._nonCapturing = nonCapturing;
316    item._length = realLength || item.length; // underlying number of sub-groups
317    return item;
318  },
319
320  toString: function() {
321    return "(<#" + this[PATTERNS].join(">)|(<#") + ">)";
322  }
323});
324
325function _nonCapture(match, escaped) {
326  return escaped || "(?:"; // non-capturing
327};
328
329// =========================================================================
330// lang/extend.js
331// =========================================================================
332
333function 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)
343        } else {
344          object[key] = value;
345        }
346      }
347    }
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);
354      } else {
355        object[key] = value;
356      }
357    }
358  }
359  return object;
360};
361
362function _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;
370    return returnValue;
371  };
372};
373
374function combine(keys, values) {
375  // Combine two arrays to make a hash.
376  if (!values) values = keys;
377  var hash = {};
378  for (var i in keys) hash[i] = values[i];
379  return hash;
380};
381
382function 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;
391  });
392};
393
394function 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) || [];
398};
399
400function rescape(string) {
401  // Make a string safe for creating a RegExp.
402  return String(string).replace(_RESCAPE, "\\$1");
403};
404
405// http://blog.stevenlevithan.com/archives/faster-trim-javascript
406function trim(string) {
407  return String(string).replace(_LTRIM, "").replace(_RTRIM, "");
408};
409
410function K(k) {
411  return function() {
412    return k;
413  };
414};
415
416// -----------------------------------------------------------------------
417// parsing
418// -----------------------------------------------------------------------
419
420var Parser = RegGrp.extend({ignoreCase: true});
421
422var SINGLE_QUOTES       = /'/g,
423    ESCAPED             = /'(\d+)'/g,
424    ESCAPE              = /\\/g,
425    UNESCAPE            = /\\([nrtf'"])/g;
426
427var strings = [];
428
429var encoder = new Parser({
430  // comments
431  "<!\\-\\-|\\-\\->": "",
432  "\\/\\*[^*]*\\*+([^\\/][^*]*\\*+)*\\/": "",
433  // get rid
434  "@(namespace|import)[^;\\n]+[;\\n]": "",
435  // strings
436  "'(\\\\.|[^'\\\\])*'": encodeString,
437  '"(\\\\.|[^"\\\\])*"': encodeString,
438  // white space
439  "\\s+": " "
440});
441
442function encode(selector) {
443  return encoder.parse(selector).replace(UNESCAPE, "$1");
444};
445
446function decode(query) {
447  // put string values back
448  return query.replace(ESCAPED, decodeString);
449};
450
451function 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 + "'";
457};
458
459function decodeString(match, index) {
460  var string = strings[index];
461  if (string == null) return match;
462  return "'" + strings[index] + "'";
463};
464
465function getString(value) {
466  return value.indexOf("'") === 0 ? strings[value.slice(1, - 1)] : value;
467};
468
469// clone a "width" function to create a "height" function
470var rotater = new RegGrp({
471  Width: "Height",
472  width: "height",
473  Left:  "Top",
474  left:  "top",
475  Right: "Bottom",
476  right: "bottom",
477  onX:   "onY"
478});
479
480function rotate(fn) {
481  return rotater.parse(fn);
482};
483
484// -----------------------------------------------------------------------
485// event handling
486// -----------------------------------------------------------------------
487
488var eventHandlers = [];
489
490function addResize(handler) {
491  addRecalc(handler);
492  addEventHandler(window, "onresize", handler);
493};
494
495// add an event handler (function) to an element
496function addEventHandler(element, type, handler) {
497  element.attachEvent(type, handler);
498  // store the handler so it can be detached later
499  eventHandlers.push(arguments);
500};
501
502// remove an event handler assigned to an element by IE7
503function removeEventHandler(element, type, handler) {
504  try {
505    element.detachEvent(type, handler);
506  } catch (ex) {
507    // write a letter of complaint to microsoft..
508  }
509};
510
511// remove event handlers (they eat memory)
512addEventHandler(window, "onunload", function() {
513  var handler;
514  while (handler = eventHandlers.pop()) {
515    removeEventHandler(handler[0], handler[1], handler[2]);
516  }
517});
518
519function 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;
525  return condition;
526};
527
528addEventHandler(window, "onbeforeprint", function() {
529  if (!IE7.CSS.print) new StyleSheet("print");
530  IE7.CSS.print.recalc();
531});
532
533// -----------------------------------------------------------------------
534// pixel conversion
535// -----------------------------------------------------------------------
536
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.
541
542var PIXEL = /^\d+(px)?$/i;
543var PERCENT = /^\d+%$/;
544var 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;
553  return value;
554};
555
556// -----------------------------------------------------------------------
557// generic
558// -----------------------------------------------------------------------
559
560var $IE7 = "ie7-";
561
562var Fix = Base.extend({
563  constructor: function() {
564    this.fixes = [];
565    this.recalcs = [];
566  },
567  init: Undefined
568});
569
570// a store for functions that will be called when refreshing IE7
571var recalcs = [];
572function addRecalc(recalc) {
573  recalcs.push(recalc);
574};
575
576IE7.recalc = function() {
577  IE7.HTML.recalc();
578  // re-apply style sheet rules (re-calculate ie7 classes)
579  IE7.CSS.recalc();
580  // apply global fixes to the document
581  for (var i = 0; i < recalcs.length; i++) recalcs[i]();
582};
583
584function isFixed(element) {
585  return element.currentStyle["ie7-position"] == "fixed";
586};
587
588// original style
589function getDefinedStyle(element, propertyName) {
590  return element.currentStyle[$IE7 + propertyName] || element.currentStyle[propertyName];
591};
592
593function setOverrideStyle(element, propertyName, value) {
594  if (element.currentStyle[$IE7 + propertyName] == null) {
595    element.runtimeStyle[$IE7 + propertyName] = element.currentStyle[propertyName];
596  }
597  element.runtimeStyle[propertyName] = value;
598};
599
600// Create a temporary element which is used to inherit styles
601// from the target element.
602function 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;
606  return element;
607};
608
609
610// =========================================================================
611// ie7-css.js
612// =========================================================================
613
614var 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 + "){";
618
619var ID_ATTRIBUTE  = "(e.nodeName==='FORM'?IE7._getAttribute(e,'id'):e.id)";
620
621var HYPERLINK = /a(#[\w-]+)?(\.[\w-]+)?:(hover|active)/i;
622var FIRST_LINE_LETTER = /(.*)(:first-(line|letter))/;
623var SPACE = /\s/;
624var RULE = /((?:\\.|[^{\\])+)\{((?:\\.|[^}\\])+)\}/g;
625var SELECTOR = /(?:\\.|[^,\\])+/g;
626
627var styleSheets = document.styleSheets;
628
629var inheritedProperties = [];
630
631IE7.CSS = new (Fix.extend({ // single instance
632  parser: new Parser,
633  screen: "",
634  print: "",
635  styles: [],
636  rules: [],
637  pseudoClasses: appVersion < 7 ? "first\\-child" : "",
638  dynamicPseudoClasses: {
639    toString: function() {
640      var strings = [];
641      for (var pseudoClass in this) strings.push(pseudoClass);
642      return strings.join("|");
643    }
644  },
645 
646  init: function() {
647    var NONE = "^\x01$";
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");
665   
666    this.createStyleSheet();
667    this.refresh();
668  },
669 
670     addEventHandler: function() {
671          addEventHandler.apply(null, arguments);
672     },
673 
674  addFix: function(expression, replacement) {
675    this.parser.add(expression, replacement);
676  },
677 
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";
687    });
688    this.recalcs.push(arguments);
689    return id;
690  },
691 
692  apply: function() {
693    this.getInlineCSS();
694    new StyleSheet("screen");
695    this.trash();
696  },
697 
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;
706  },
707 
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;
713      }
714    }
715  },
716 
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).
721
722    // load the style sheet text from an external file
723    try {
724      var cssText = styleSheet.cssText;
725    } catch (e) {
726      cssText = "";
727    }
728    if (httpRequest) cssText = loadFile(styleSheet.href, path) || cssText;
729    return cssText;
730  },
731 
732  recalc: function() {
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
756        //  to each element
757        if (elements.length) for (j = 0; j < calcs.length; j++) {
758          // get the matching flag (e.g. ie7_recalc3)
759          id = calcs[j];
760          // extract the numeric id from the end of the flag
761          //  and use it to index the collection of recalc
762          //  functions
763          calc = IE7.CSS.recalcs[id.slice(10)][2];
764          for (k = 0; (element = elements[k]); k++) {
765            // apply the fix
766            if (element.currentStyle[id]) calc(element, cssText);
767          }
768        }
769      }
770    }
771  },
772 
773  refresh: function() {
774    this.styleSheet.cssText = HEADER + this.screen + this.print;
775  },
776 
777  trash: function() {
778    // trash the old style sheets
779    for (var i = 0; i < styleSheets.length; i++) {
780      if (!styleSheets[i].ie7) {
781        try {
782          var cssText = styleSheets[i].cssText;
783        } catch (e) {
784          cssText = "";
785        }
786        if (cssText) styleSheets[i].cssText = "";
787      }
788    }
789  }
790}));
791
792// -----------------------------------------------------------------------
793//  IE7 StyleSheet class
794// -----------------------------------------------------------------------
795
796var StyleSheet = Base.extend({
797  constructor: function(media) {
798    this.media = media;
799    this.load();
800    IE7.CSS[media] = this;
801    IE7.CSS.refresh();
802  },
803 
804  createRule: function(selector, cssText) {
805    var match;
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);
811      }
812    } else {
813      return new Rule(selector, cssText);
814    }
815    return selector + " {" + cssText + "}";
816  },
817 
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;
825
826    var self = this;
827   
828    // Store loaded cssText URLs
829    var fileCache = {};
830   
831    function getCSSText(styleSheet, path, media, level) {
832      var cssText = "";
833      if (!level) {
834        media = toSimpleMedia(styleSheet.media);
835        level = 0;
836      }
837      if (media === "none") {
838        styleSheet.disabled = true;
839        return "";
840      }
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        try {
845          var canAcess = !!styleSheet.cssText;
846        } catch (exe) {}
847        if (level < 3 && canAcess) {
848          var hrefs = styleSheet.cssText.match(IMPORTS);
849          // loop through imported style sheets
850          for (var i = 0, imported; i < styleSheet.imports.length; i++) {
851            var imported = styleSheet.imports[i];
852            var href = styleSheet._href || styleSheet.href;
853            imported._href = hrefs[i].replace(TRIM_IMPORTS, "");
854            // call this function recursively to get all imported style sheets
855            cssText += getCSSText(imported, getPath(href, path), media, level + 1);
856          }
857        }
858        // retrieve inline style or load an external style sheet
859        cssText += encode(styleSheet.href ? loadStyleSheet(styleSheet, path) : styleSheet.owningElement._cssText);
860        cssText = parseMedia(cssText, self.media);
861      }
862      return cssText;
863    };
864
865    // Load all style sheets in the document
866    for (var i = 0; i < styleSheets.length; i++) {
867      var styleSheet = styleSheets[i];
868      if (!styleSheet.disabled && !styleSheet.ie7) this.cssText += getCSSText(styleSheet);
869    }
870   
871    // helper functions
872    function parseMedia(cssText, media) {
873      filterMedia.value = media;
874      return cssText.replace(MEDIA, filterMedia);
875    };
876   
877    function filterMedia(match, media, cssText) {
878      media = toSimpleMedia(media);
879      switch (media) {
880        case "screen":
881        case "print":
882          if (media !== filterMedia.value) return "";
883        case "all":
884          return cssText;
885      }
886      return "";
887    };
888   
889    function toSimpleMedia(media) {
890      if (!media) return "all";
891      var split = media.toLowerCase().split(/\s*,\s*/);
892      media = "none";
893      for (var i = 0; i < split.length; i++) {
894        if (split[i] === "all") return "all";
895        if (split[i] === "screen") {
896          if (media === "print") return "all";
897          media = "screen";
898        } else if (split[i] === "print") {
899          if (media === "screen") return "all";
900          media = "print";
901        }
902      }
903      return media;
904    };
905   
906    // Load an external style sheet
907    function loadStyleSheet(styleSheet, path) {
908      var href = styleSheet._href || styleSheet.href;
909      var url = makePath(href, path);
910      // If the style sheet has already loaded then don't reload it
911      if (fileCache[url]) return "";
912      // Load from source
913      fileCache[url] = styleSheet.disabled ? "" :
914        fixUrls(IE7.CSS.getText(styleSheet, path), getPath(href, path));
915      return fileCache[url];
916    };
917
918    // Fix CSS paths.
919    // We're lumping all css text into one big style sheet so relative
920    // paths have to be fixed. This is necessary anyway because of other
921    // Internet Explorer bugs.
922    function fixUrls(cssText, pathname) {
923      // hack & slash
924      return cssText.replace(URL, "$1" + pathname.slice(0, pathname.lastIndexOf("/") + 1) + "$2");
925    };
926  },
927 
928  load: function() {
929    this.cssText = "";
930    this.getText();
931    this.parse();
932    if (inheritedProperties.length) {
933      this.cssText = parseInherited(this.cssText);
934    }
935    this.cssText = decode(this.cssText);
936    fileCache = {};
937  },
938 
939  parse: function() {
940    var cssText = IE7.CSS.parser.parse(this.cssText);
941   
942    var declarations = "";
943    this.cssText = cssText.replace(/@charset[^;]+;|@font\-face[^\}]+\}/g, function(match) {
944      declarations += match + "\n";
945      return "";
946    });
947    this.declarations = decode(declarations);
948   
949    // Parse the style sheet
950    var offset = IE7.CSS.rules.length;
951    var rules = [], rule;
952    while ((rule = RULE.exec(this.cssText))) {
953      var cssText = rule[2];
954      if (cssText) {
955        var fixDescendants = appVersion < 7 && cssText.indexOf("AlphaImageLoader") !== -1;
956        var selectors = rule[1].match(SELECTOR), selector;
957        for (var i = 0; selector = selectors[i]; i++) {
958          selector = trim(selector);
959          var isUnknown = IE7.CSS.UNKNOWN.test(selector);
960          selectors[i] = isUnknown ? this.createRule(selector, cssText) : selector + "{" + cssText + "}";
961          if (fixDescendants) selectors[i] += this.createRule(selector + ">*", "position:relative");
962        }
963        rules.push(selectors.join("\n"));
964      }
965    }
966    this.cssText = rules.join("\n");
967    this.rules = IE7.CSS.rules.slice(offset);
968  },
969 
970  recalc: function() {
971    var rule, i;
972    for (i = 0; (rule = this.rules[i]); i++) rule.recalc();
973  },
974 
975  toString: function() {
976    return this.declarations + "@media " + this.media + "{" + this.cssText + "}";
977  }
978});
979
980var PseudoElement;
981
982// -----------------------------------------------------------------------
983// IE7 style rules
984// -----------------------------------------------------------------------
985
986var Rule = IE7.Rule = Base.extend({
987  constructor: function(selector, cssText) {
988    this.id = IE7.CSS.rules.length;
989    this.className = Rule.PREFIX + this.id;
990    var pseudoElement = selector.match(FIRST_LINE_LETTER);
991    this.selector = (pseudoElement ? pseudoElement[1] : selector) || "*";
992    this.selectorText = this.parse(this.selector) + (pseudoElement ? pseudoElement[2] : "");
993    this.cssText = cssText;
994    this.MATCH = new RegExp("\\s" + this.className + "(\\s|$)", "g");
995    IE7.CSS.rules.push(this);
996    this.init();
997  },
998 
999  init: Undefined,
1000 
1001  add: function(element) {
1002    // allocate this class
1003    element.className += " " + this.className;
1004  },
1005 
1006  recalc: function() {
1007    // execute the underlying css query for this class
1008    var match = cssQuery(this.selector);
1009    // add the class name for all matching elements
1010    for (var i = 0; i < match.length; i++) this.add(match[i]);
1011  },
1012
1013  parse: function(selector) {
1014    // attempt to preserve specificity for "loose" parsing by
1015    //  removing unknown tokens from a css selector but keep as
1016    //  much as we can..
1017    var simple = selector.replace(Rule.CHILD, " ").replace(Rule.COMPLEX, "");
1018    if (appVersion < 7) simple = simple.replace(Rule.MULTI, "");
1019    var tags = match(simple, Rule.TAGS).length - match(selector, Rule.TAGS).length;
1020    var classes = match(simple, Rule.CLASSES).length - match(selector, Rule.CLASSES).length + 1;
1021    while (classes > 0 && Rule.CLASS.test(simple)) {
1022      simple = simple.replace(Rule.CLASS, "");
1023      classes--;
1024    }
1025    while (tags > 0 && Rule.TAG.test(simple)) {
1026      simple = simple.replace(Rule.TAG, "$1*");
1027      tags--;
1028    }
1029    simple += "." + this.className;
1030    classes = Math.min(classes, 2);
1031    tags = Math.min(tags, 2);
1032    var score = -10 * classes - tags;
1033    if (score > 0) {
1034      simple = simple + "," + Rule.MAP[score] + " " + simple;
1035    }
1036    return simple;
1037  },
1038 
1039  remove: function(element) {
1040    // deallocate this class
1041    element.className = element.className.replace(this.MATCH, "$1");
1042  },
1043 
1044  toString: function() {
1045    return format("%1 {%2}", this.selectorText, this.cssText);
1046  }
1047}, {
1048  CHILD: />/g,
1049  CLASS: /\.[\w-]+/,
1050  CLASSES: /[.:\[]/g,
1051  MULTI: /(\.[\w-]+)+/g,
1052  PREFIX: "ie7_class",
1053  TAG: /^\w+|([\s>+~])\w+/,
1054  TAGS: /^\w|[\s>+~]\w/g,
1055  MAP: {
1056    "1":  "html",
1057    "2":  "html body",
1058    "10": ".ie7_html",
1059    "11": "html.ie7_html",
1060    "12": "html.ie7_html body",
1061    "20": ".ie7_html .ie7_body",
1062    "21": "html.ie7_html .ie7_body",
1063    "22": "html.ie7_html body.ie7_body"
1064  }
1065});
1066
1067// -----------------------------------------------------------------------
1068// IE7 dynamic style
1069// -----------------------------------------------------------------------
1070
1071// object properties:
1072// attach: the element that an event handler will be attached to
1073// target: the element that will have the IE7 class applied
1074
1075var DynamicRule = Rule.extend({
1076  // properties
1077  constructor: function(selector, attach, dynamicPseudoClass, target, cssText) {
1078    this.negated = dynamicPseudoClass.indexOf("not") === 0;
1079    if (this.negated) dynamicPseudoClass = dynamicPseudoClass.slice(5, -1);
1080    // initialise object properties
1081    this.attach = attach || "*";
1082    this.dynamicPseudoClass = IE7.CSS.dynamicPseudoClasses[dynamicPseudoClass];
1083    this.target = target;
1084    this.base(selector, cssText);
1085  },
1086 
1087  recalc: function() {
1088    // execute the underlying css query for this class
1089    var attaches = cssQuery(this.attach), attach;
1090    // process results
1091    for (var i = 0; attach = attaches[i]; i++) {
1092      // retrieve the event handler's target element(s)
1093      var target = this.target ? cssQuery(this.target, attach) : [attach];
1094      // attach event handlers for dynamic pseudo-classes
1095      if (target.length) this.dynamicPseudoClass.apply(attach, target, this);
1096    }
1097  }
1098});
1099
1100// -----------------------------------------------------------------------
1101//  IE7 dynamic pseudo-classes
1102// -----------------------------------------------------------------------
1103
1104var DynamicPseudoClass = Base.extend({
1105  constructor: function(name, apply) {
1106    this.name = name;
1107    this.apply = apply;
1108    this.instances = {};
1109    IE7.CSS.dynamicPseudoClasses[name] = this;
1110  },
1111 
1112  register: function(instance, negated) {
1113    // an "instance" is actually an Arguments object
1114    var _class = instance[2];
1115    if (!negated && _class.negated) {
1116      this.unregister(instance, true);
1117    } else {
1118      instance.id = _class.id + instance[0].uniqueID;
1119      if (!this.instances[instance.id]) {
1120        var target = instance[1], j;
1121        for (j = 0; j < target.length; j++) _class.add(target[j]);
1122        this.instances[instance.id] = instance;
1123      }
1124    }
1125  },
1126 
1127  unregister: function(instance, negated) {
1128    var _class = instance[2];
1129    if (!negated && _class.negated) {
1130      this.register(instance, true);
1131    } else {
1132      if (this.instances[instance.id]) {
1133        var target = instance[1], j;
1134        for (j = 0; j < target.length; j++) _class.remove(target[j]);
1135        delete this.instances[instance.id];
1136      }
1137    }
1138  }
1139});
1140 
1141// -----------------------------------------------------------------------
1142// dynamic pseudo-classes
1143// -----------------------------------------------------------------------
1144
1145var Hover = new DynamicPseudoClass("hover", function(element) {
1146  var instance = arguments;
1147  IE7.CSS.addEventHandler(element, "onmouseenter", function() {
1148    Hover.register(instance);
1149  });
1150  IE7.CSS.addEventHandler(element, "onmouseleave", function() {
1151    Hover.unregister(instance);
1152  });
1153});
1154
1155// globally trap the mouseup event (thanks Martijn!)
1156addEventHandler(document, "onmouseup", function() {
1157  var instances = Hover.instances;
1158  for (var i in instances)
1159    if (!instances[i][0].contains(event.srcElement))
1160      Hover.unregister(instances[i]);
1161});
1162
1163var ATTR = {
1164  "=":  "%1==='%2'",                           // "[@%1='%2']"
1165  "~=": "(' '+%1+' ').indexOf(' %2 ')!==-1",   // "[contains(concat(' ',@%1,' '),' %2 ')]",
1166  "|=": "%1==='%2'||%1.indexOf('%2-')===0",    // "[@%1='%2' or starts-with(@%1,'%2-')]",
1167  "^=": "%1.indexOf('%2')===0",                // "[starts-with(@%1,'%2')]",
1168  "$=": "%1.slice(-'%2'.length)==='%2'",       // "[ends-with(@%1,'%2')]",
1169  "*=": "%1.indexOf('%2')!==-1"                // "[contains(@%1,'%2')]"
1170};
1171ATTR[""] = "%1!=null";                         // "[@%1]"
1172
1173var FILTER = {
1174  "<#attr>": function(match, name, operator, value) {
1175    var attr = "IE7._getAttribute(e,'" + name + "')";
1176    value = getString(value);
1177    if (operator.length > 1) {
1178      if (!value || operator === "~=" && SPACE.test(value)) {
1179        return "false&&";
1180      }
1181      attr = "(" + attr + "||'')";
1182    }
1183    return "(" + format(ATTR[operator], attr, value) + ")&&";
1184  },
1185
1186  "<#id>":    ID_ATTRIBUTE + "==='$1'&&",
1187
1188  "<#class>": "e.className&&(' '+e.className+' ').indexOf(' $1 ')!==-1&&",
1189
1190  // PSEDUO
1191  ":first-child":     "!" + PREVIOUS_SIBLING + "&&",
1192  ":link":           "e.currentStyle['ie7-link']=='link'&&",
1193  ":visited":        "e.currentStyle['ie7-link']=='visited'&&"
1194};
1195
1196// =========================================================================
1197// ie7-html.js
1198// =========================================================================
1199
1200// default font-sizes
1201//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}";
1202
1203IE7.HTML = new (Fix.extend({ // single instance 
1204  fixed: {},
1205 
1206  init: Undefined,
1207 
1208  addFix: function() {
1209    // fixes are a one-off, they are applied when the document is loaded
1210    this.fixes.push(arguments);
1211  },
1212 
1213  apply: function() {
1214    for (var i = 0; i < this.fixes.length; i++) {
1215      var match = cssQuery(this.fixes[i][0]);
1216      var fix = this.fixes[i][1];
1217      for (var j = 0; j < match.length; j++) fix(match[j]);
1218    }
1219  },
1220 
1221  addRecalc: function() {
1222    // recalcs occur whenever the document is refreshed using document.recalc()
1223    this.recalcs.push(arguments);
1224  },
1225 
1226  recalc: function() {
1227    // loop through the fixes
1228    for (var i = 0; i < this.recalcs.length; i++) {
1229      var match = cssQuery(this.recalcs[i][0]);
1230      var recalc = this.recalcs[i][1], element;
1231      var key = Math.pow(2, i);
1232      for (var j = 0; (element = match[j]); j++) {
1233        var uniqueID = element.uniqueID;
1234        if ((this.fixed[uniqueID] & key) === 0) {
1235          element = recalc(element) || element;
1236          this.fixed[uniqueID] |= key;
1237        }
1238      }
1239    }
1240  }
1241}));
1242
1243if (appVersion < 7) { 
1244  // provide support for the <abbr> tag.
1245  document.createElement("abbr");
1246 
1247  // bind to the first child control
1248  IE7.HTML.addRecalc("label", function(label) {
1249    if (!label.htmlFor) {
1250      var firstChildControl = cssQuery("input,textarea", label, true);
1251      if (firstChildControl) {
1252        addEventHandler(label, "onclick", function() {
1253          firstChildControl.click();
1254        });
1255      }
1256    }
1257  });
1258}
1259
1260// =========================================================================
1261// ie7-layout.js
1262// =========================================================================
1263
1264var NUMERIC = "[.\\d]";
1265
1266(function() {
1267  var layout = IE7.Layout = {};
1268
1269  // big, ugly box-model hack + min/max stuff
1270
1271  // #tantek > #erik > #dean { voice-family: hacker; }
1272
1273  // -----------------------------------------------------------------------
1274  // "layout"
1275  // -----------------------------------------------------------------------
1276
1277  HEADER += "*{boxSizing:content-box}";
1278
1279  // give an element "layout"
1280  layout.boxSizing = function(element) {
1281    if (!element.currentStyle.hasLayout) {
1282    //#  element.runtimeStyle.fixedHeight =
1283      element.style.height = "0cm";
1284      if (element.currentStyle.verticalAlign === "auto")
1285        element.runtimeStyle.verticalAlign = "top";
1286      // when an element acquires "layout", margins no longer collapse correctly
1287      collapseMargins(element);
1288    }
1289  };
1290
1291  // -----------------------------------------------------------------------
1292  // Margin Collapse
1293  // -----------------------------------------------------------------------
1294
1295  function collapseMargins(element) {
1296    if (element != viewport && element.currentStyle.position !== "absolute") {
1297      collapseMargin(element, "marginTop");
1298      collapseMargin(element, "marginBottom");
1299    }
1300  };
1301
1302  function collapseMargin(element, type) {
1303    if (!element.runtimeStyle[type]) {
1304      var parentElement = element.parentElement;
1305      var isTopMargin = type === "marginTop";
1306      if (parentElement && parentElement.currentStyle.hasLayout && !IE7._getElementSibling(element, isTopMargin ? "previous" : "next")) return;
1307      var child = element[isTopMargin ? "firstChild" : "lastChild"];
1308      if (child && child.nodeName < "@") child = IE7._getElementSibling(child, isTopMargin ? "next" : "previous");
1309      if (child && child.currentStyle.styleFloat === "none" && child.currentStyle.hasLayout) {
1310        collapseMargin(child, type);
1311        margin = _getMargin(element, element.currentStyle[type]);
1312        childMargin = _getMargin(child, child.currentStyle[type]);
1313        if (margin < 0 || childMargin < 0) {
1314          element.runtimeStyle[type] = margin + childMargin;
1315        } else {
1316          element.runtimeStyle[type] = Math.max(childMargin, margin);
1317        }
1318        child.runtimeStyle[type] = "0px";
1319      }
1320    }
1321  };
1322
1323  function _getMargin(element, value) {
1324    return value === "auto" ? 0 : getPixelValue(element, value);
1325  };
1326
1327  // -----------------------------------------------------------------------
1328  // box-model
1329  // -----------------------------------------------------------------------
1330
1331  // constants
1332  var UNIT = /^[.\d][\w]*$/, AUTO = /^(auto|0cm)$/;
1333
1334  var apply = {};
1335  layout.borderBox = function(element){
1336    apply.Width(element);
1337    apply.Height(element);
1338  };
1339
1340  var _fixWidth = function(HEIGHT) {
1341    apply.Width = function(element) {
1342      if (!PERCENT.test(element.currentStyle.width)) _fixWidth(element);
1343      if (HEIGHT) collapseMargins(element);
1344    };
1345
1346    function _fixWidth(element, value) {
1347      if (!element.runtimeStyle.fixedWidth) {
1348        if (!value) value = element.currentStyle.width;
1349        element.runtimeStyle.fixedWidth = UNIT.test(value) ? Math.max(0, getFixedWidth(element, value)) + "px" : value;
1350        setOverrideStyle(element, "width", element.runtimeStyle.fixedWidth);
1351      }
1352    };
1353
1354    function layoutWidth(element) {
1355      if (!isFixed(element)) {
1356        var layoutParent = element.offsetParent;
1357        while (layoutParent && !layoutParent.currentStyle.hasLayout) layoutParent = layoutParent.offsetParent;
1358      }
1359      return (layoutParent || viewport).clientWidth;
1360    };
1361
1362    function getPixelWidth(element, value) {
1363      if (PERCENT.test(value)) return parseInt(parseFloat(value) / 100 * layoutWidth(element));
1364      return getPixelValue(element, value);
1365    };
1366
1367    var getFixedWidth = function(element, value) {
1368      var borderBox = element.currentStyle["ie7-box-sizing"] === "border-box";
1369      var adjustment = 0;
1370      if (MSIE5 && !borderBox)
1371        adjustment += getBorderWidth(element) + getWidth(element, "padding");
1372      else if (!MSIE5 && borderBox)
1373        adjustment -= getBorderWidth(element) + getWidth(element, "padding");
1374      return getPixelWidth(element, value) + adjustment;
1375    };
1376
1377    // easy way to get border thickness for elements with "layout"
1378    function getBorderWidth(element) {
1379      return element.offsetWidth - element.clientWidth;
1380    };
1381
1382    // have to do some pixel conversion to get padding/margin thickness :-(
1383    function getWidth(element, type) {
1384      return getPixelWidth(element, element.currentStyle[type + "Left"]) + getPixelWidth(element, element.currentStyle[type + "Right"]);
1385    };
1386
1387    // -----------------------------------------------------------------------
1388    // min/max
1389    // -----------------------------------------------------------------------
1390
1391    HEADER += "*{minWidth:none;maxWidth:none;min-width:none;max-width:none}";
1392
1393    // handle min-width property
1394    layout.minWidth = function(element) {
1395      // IE6 supports min-height so we frig it here
1396      //#if (element.currentStyle.minHeight === "auto") element.runtimeStyle.minHeight = 0;
1397      if (element.currentStyle["min-width"] != null) {
1398        element.style.minWidth = element.currentStyle["min-width"];
1399      }
1400      if (register(arguments.callee, element, element.currentStyle.minWidth !== "none")) {
1401        layout.boxSizing(element);
1402        _fixWidth(element);
1403        resizeWidth(element);
1404      }
1405    };
1406
1407    // clone the minWidth function to make a maxWidth function
1408    eval("IE7.Layout.maxWidth=" + String(layout.minWidth).replace(/min/g, "max"));
1409
1410    // apply min/max restrictions
1411    function resizeWidth(element) {
1412      // check boundaries
1413      if (element == document.body) {
1414        var width = element.clientWidth;
1415      } else {
1416        var rect = element.getBoundingClientRect();
1417        width = rect.right - rect.left;
1418      }
1419      if (element.currentStyle.minWidth !== "none" && width < getFixedWidth(element, element.currentStyle.minWidth)) {
1420        element.runtimeStyle.width = element.currentStyle.minWidth;
1421      } else if (element.currentStyle.maxWidth !== "none" && width >= getFixedWidth(element, element.currentStyle.maxWidth)) {
1422        element.runtimeStyle.width = element.currentStyle.maxWidth;
1423      } else {
1424        element.runtimeStyle.width = element.runtimeStyle.fixedWidth;
1425      }
1426    };
1427
1428    // -----------------------------------------------------------------------
1429    // right/bottom
1430    // -----------------------------------------------------------------------
1431
1432    function fixRight(element) {
1433      if (register(fixRight, element, /^(fixed|absolute)$/.test(element.currentStyle.position) &&
1434        getDefinedStyle(element, "left") !== "auto" &&
1435        getDefinedStyle(element, "right") !== "auto" &&
1436        AUTO.test(getDefinedStyle(element, "width")))) {
1437          resizeRight(element);
1438          layout.boxSizing(element);
1439      }
1440    };
1441    layout.fixRight = fixRight;
1442
1443    function resizeRight(element) {
1444      var left = getPixelWidth(element, element.runtimeStyle._left || element.currentStyle.left);
1445      var width = layoutWidth(element) - getPixelWidth(element, element.currentStyle.right) -  left - getWidth(element, "margin");
1446      if (parseInt(element.runtimeStyle.width) === width) return;
1447      element.runtimeStyle.width = "";
1448      if (isFixed(element) || HEIGHT || element.offsetWidth < width) {
1449        if (!MSIE5) width -= getBorderWidth(element) + getWidth(element, "padding");
1450        if (width < 0) width = 0;
1451        element.runtimeStyle.fixedWidth = width;
1452        setOverrideStyle(element, "width", width);
1453      }
1454    };
1455
1456  // -----------------------------------------------------------------------
1457  // window.onresize
1458  // -----------------------------------------------------------------------
1459
1460    // handle window resize
1461    var clientWidth = 0;
1462    addResize(function() {
1463      if (!viewport) return;
1464      var i, wider = (clientWidth < viewport.clientWidth);
1465      clientWidth = viewport.clientWidth;
1466      // resize elements with "min-width" set
1467      var elements = layout.minWidth.elements;
1468      for (i in elements) {
1469        var element = elements[i];
1470        var fixedWidth = (parseInt(element.runtimeStyle.width) === getFixedWidth(element, element.currentStyle.minWidth));
1471        if (wider && fixedWidth) element.runtimeStyle.width = "";
1472        if (wider == fixedWidth) resizeWidth(element);
1473      }
1474      // resize elements with "max-width" set
1475      var elements = layout.maxWidth.elements;
1476      for (i in elements) {
1477        var element = elements[i];
1478        var fixedWidth = (parseInt(element.runtimeStyle.width) === getFixedWidth(element, element.currentStyle.maxWidth));
1479        if (!wider && fixedWidth) element.runtimeStyle.width = "";
1480        if (wider !== fixedWidth) resizeWidth(element);
1481      }
1482      // resize elements with "right" set
1483      for (i in fixRight.elements) resizeRight(fixRight.elements[i]);
1484    });
1485
1486  // -----------------------------------------------------------------------
1487  // fix CSS
1488  // -----------------------------------------------------------------------
1489    if (MSIE5) {
1490      IE7.CSS.addRecalc("width", NUMERIC, apply.Width);
1491    }
1492    if (appVersion < 7) {
1493      IE7.CSS.addRecalc("max-width", NUMERIC, layout.maxWidth);
1494      IE7.CSS.addRecalc("right", NUMERIC, fixRight);
1495    } else if (appVersion == 7) {
1496      if (HEIGHT) IE7.CSS.addRecalc("height", "[\\d.]+%", function(element) {
1497        element.runtimeStyle.pixelHeight = parseInt(layoutWidth(element) * element.currentStyle["ie7-height"].slice(0, -1) / 100);
1498      });
1499    }
1500  };
1501
1502  eval("var _fixHeight=" + rotate(_fixWidth));
1503
1504  // apply box-model + min/max fixes
1505  _fixWidth();
1506  _fixHeight(true);
1507 
1508  if (appVersion < 7) {
1509    IE7.CSS.addRecalc("min-width", NUMERIC, layout.minWidth);
1510    IE7.CSS.addFix(/\bmin-height\s*/, "height");
1511  }
1512})();
1513
1514// =========================================================================
1515// ie7-graphics.js
1516// =========================================================================
1517
1518// a small transparent image used as a placeholder
1519var BLANK_GIF = makePath("blank.gif", path);
1520
1521var ALPHA_IMAGE_LOADER = "DXImageTransform.Microsoft.AlphaImageLoader";
1522var PNG_FILTER = "progid:" + ALPHA_IMAGE_LOADER + "(src='%1',sizingMethod='%2')";
1523 
1524// regular expression version of the above
1525var PNG;
1526
1527var filtered = [];
1528
1529function fixImage(element) {
1530  if (PNG.test(element.src)) {
1531    // we have to preserve width and height
1532    var image = new Image(element.width, element.height);
1533    image.onload = function() {
1534      element.width = image.width;
1535      element.height = image.height;
1536      image = null;
1537    };
1538    image.src = element.src;
1539    // store the original url (we'll put it back when it's printed)
1540    element.pngSrc = element.src;
1541    // add the AlphaImageLoader thingy
1542    addFilter(element);
1543  }
1544};
1545
1546if (appVersion < 7) {
1547  // ** IE7 VARIABLE
1548  // e.g. apply the hack to all files ending in ".png"
1549  // IE7_PNG_SUFFIX = ".png";
1550  // You can also set it to a RegExp
1551  // IE7_PNG_SUFFIX = /\d+\.png$/;
1552
1553  // replace background(-image): url(..) ..  with background(-image): .. ;filter: ..;
1554  IE7.CSS.addFix(/background(-image)?\s*:\s*([^};]*)?url\(([^\)]+)\)([^;}]*)?/, function(match, $1, $2, url, $4) {
1555    url = getString(url);
1556    return PNG.test(url) ? "filter:" + format(PNG_FILTER, url, $4.indexOf("no-repeat") === -1 ? "scale" : "crop") +
1557      ";zoom:1;background" + ($1||"") + ":" + ($2||"") + "none" + ($4||"") : match;
1558  });
1559
1560  // list-style-image
1561  IE7.CSS.addRecalc(/list\-style(\-image)?/, "[^};]*url", function(element) {
1562    var url = element.currentStyle.listStyleImage.slice(5, -2);
1563    if (PNG.test(url)) {
1564      if (element.nodeName === "LI") {
1565        fixListStyleImage(element, url)
1566      } else if (element.nodeName === "UL") {
1567        for (var i = 0, li; li = element.childNodes[i]; i++) {
1568          if (li.nodeName === "LI") fixListStyleImage(li, url);
1569        }
1570      }
1571    }
1572  });
1573
1574  function fixListStyleImage(element, src) {
1575    var style = element.runtimeStyle;
1576    var originalHeight = element.offsetHeight;
1577    var image = new Image;
1578    image.onload = function() {
1579      var paddingLeft = element.currentStyle.paddingLeft;
1580      paddingLeft = paddingLeft === "0px" ? 0 : getPixelValue(element, paddingLeft);
1581      style.paddingLeft = (paddingLeft + this.width) + "px";
1582      style.marginLeft = -this.width + "px";
1583      style.listStyleType = "none";
1584      style.listStyleImage = "none";
1585      style.paddingTop = Math.max(originalHeight - element.offsetHeight, 0) + "px";
1586      addFilter(element, "crop", src);
1587      element.style.zoom = "100%";
1588    };
1589    image.src = src;
1590  };
1591 
1592  // -----------------------------------------------------------------------
1593  //  fix PNG transparency (HTML images)
1594  // -----------------------------------------------------------------------
1595
1596  IE7.HTML.addRecalc("img,input", function(element) {
1597    if (element.nodeName === "INPUT" && element.type !== "image") return;
1598    fixImage(element);
1599    addEventHandler(element, "onpropertychange", function() {
1600      if (!printing && event.propertyName === "src" &&
1601        element.src.indexOf(BLANK_GIF) === -1) fixImage(element);
1602    });
1603  });
1604
1605  // assume that background images should not be printed
1606  //  (if they are not transparent then they'll just obscure content)
1607  // but we'll put foreground images back...
1608  var printing = false;
1609  addEventHandler(window, "onbeforeprint", function() {
1610    printing = true;
1611    for (var i = 0; i < filtered.length; i++) removeFilter(filtered[i]);
1612  });
1613  addEventHandler(window, "onafterprint", function() {
1614    for (var i = 0; i < filtered.length; i++) addFilter(filtered[i]);
1615    printing = false;
1616  });
1617}
1618
1619// apply a filter
1620function addFilter(element, sizingMethod, src) {
1621  var filter = element.filters[ALPHA_IMAGE_LOADER];
1622  if (filter) {
1623    filter.src = src || element.src;
1624    filter.enabled = true;
1625  } else {
1626    element.runtimeStyle.filter = format(PNG_FILTER, src || element.src, sizingMethod || "scale");
1627    filtered.push(element);
1628  }
1629  // remove the real image
1630  element.src = BLANK_GIF;
1631};
1632
1633function removeFilter(element) {
1634  element.src = element.pngSrc;
1635  element.filters[ALPHA_IMAGE_LOADER].enabled = false;
1636};
1637
1638// =========================================================================
1639// ie7-fixed.js
1640// =========================================================================
1641
1642(function() {
1643  if (appVersion >= 7) return;
1644 
1645  // some things to consider for this hack.
1646  // the document body requires a fixed background. even if
1647  //  it is just a blank image.
1648  // you have to use setExpression instead of onscroll, this
1649  //  together with a fixed body background helps avoid the
1650  //  annoying screen flicker of other solutions.
1651 
1652  IE7.CSS.addRecalc("position", "fixed", _positionFixed, "absolute");
1653  IE7.CSS.addRecalc("background(-attachment)?", "[^};]*fixed", _backgroundFixed);
1654 
1655  // scrolling is relative to the documentElement (HTML tag) when in
1656  //  standards mode, otherwise it's relative to the document body
1657  var $viewport = MSIE5 ? "body" : "documentElement";
1658 
1659  function _fixBackground() {
1660    // this is required by both position:fixed and background-attachment:fixed.
1661    // it is necessary for the document to also have a fixed background image.
1662    // we can fake this with a blank image if necessary
1663    if (body.currentStyle.backgroundAttachment !== "fixed") {
1664      if (body.currentStyle.backgroundImage === "none") {
1665        body.runtimeStyle.backgroundRepeat = "no-repeat";
1666        body.runtimeStyle.backgroundImage = "url(" + BLANK_GIF + ")"; // dummy
1667      }
1668      body.runtimeStyle.backgroundAttachment = "fixed";
1669    }
1670    _fixBackground = Undefined;
1671  };
1672 
1673  var _tmp = createTempElement("img");
1674 
1675  function _isFixed(element) {
1676    return element ? isFixed(element) || _isFixed(element.parentElement) : false;
1677  };
1678 
1679  function _setExpression(element, propertyName, expression) {
1680    setTimeout("document.all." + element.uniqueID + ".runtimeStyle.setExpression('" + propertyName + "','" + expression + "')", 0);
1681  };
1682 
1683  // -----------------------------------------------------------------------
1684  //  backgroundAttachment: fixed
1685  // -----------------------------------------------------------------------
1686 
1687  function _backgroundFixed(element) {
1688    if (register(_backgroundFixed, element, element.currentStyle.backgroundAttachment === "fixed" && !element.contains(body))) {
1689      _fixBackground();
1690      util.bgLeft(element);
1691      util.bgTop(element);
1692      _backgroundPosition(element);
1693    }
1694  };
1695 
1696  function _backgroundPosition(element) {
1697    _tmp.src = element.currentStyle.backgroundImage.slice(5, -2);
1698    var parentElement = element.canHaveChildren ? element : element.parentElement;
1699    parentElement.appendChild(_tmp);
1700    util.setOffsetLeft(element);
1701    util.setOffsetTop(element);
1702    parentElement.removeChild(_tmp);
1703  };
1704 
1705  // -----------------------------------------------------------------------
1706  //  position: fixed
1707  // -----------------------------------------------------------------------
1708 
1709  function _positionFixed(element) {
1710    if (register(_positionFixed, element, isFixed(element))) {
1711      setOverrideStyle(element, "position",  "absolute");
1712      setOverrideStyle(element, "left",  element.currentStyle.left);
1713      setOverrideStyle(element, "top",  element.currentStyle.top);
1714      _fixBackground();
1715      IE7.Layout.fixRight(element);
1716      //IE7.Layout.fixBottom(element);
1717      _foregroundPosition(element);
1718    }
1719  };
1720 
1721  function _foregroundPosition(element, recalc) {
1722    document.body.getBoundingClientRect(); // force a reflow
1723    util.positionTop(element, recalc);
1724    util.positionLeft(element, recalc, true);
1725    if (!element.runtimeStyle.autoLeft && element.currentStyle.marginLeft === "auto" &&
1726      element.currentStyle.right !== "auto") {
1727      var left = viewport.clientWidth - util.getPixelWidth(element, element.currentStyle.right) -
1728        util.getPixelWidth(element, element.runtimeStyle._left) - element.clientWidth;
1729      if (element.currentStyle.marginRight === "auto") left = parseInt(left / 2);
1730      if (_isFixed(element.offsetParent)) element.runtimeStyle.pixelLeft += left;
1731      else element.runtimeStyle.shiftLeft = left;
1732    }
1733    if (!element.runtimeStyle.fixedWidth) util.clipWidth(element);
1734    if (!element.runtimeStyle.fixedHeight) util.clipHeight(element);
1735  };
1736 
1737  // -----------------------------------------------------------------------
1738  //  capture window resize
1739  // -----------------------------------------------------------------------
1740 
1741  function _resize() {
1742    // if the window has been resized then some positions need to be
1743    //  recalculated (especially those aligned to "right" or "top"
1744    var elements = _backgroundFixed.elements;
1745    for (var i in elements) _backgroundPosition(elements[i]);
1746    elements = _positionFixed.elements;
1747    for (i in elements) {
1748      _foregroundPosition(elements[i], true);
1749      _foregroundPosition(elements[i], true);
1750    }
1751    _timer = 0;
1752  };
1753 
1754  // use a timer (sometimes this is a good way to prevent resize loops)
1755  var _timer;
1756  addResize(function() {
1757    if (!_timer) _timer = setTimeout(_resize, 100);
1758  });
1759
1760  // -----------------------------------------------------------------------
1761  //  rotated
1762  // -----------------------------------------------------------------------
1763
1764  var util = {};
1765 
1766  var _horizontal = function(util) {
1767    util.bgLeft = function(element) {
1768      element.style.backgroundPositionX = element.currentStyle.backgroundPositionX;
1769      if (!_isFixed(element)) {
1770        _setExpression(element, "backgroundPositionX", "(parseInt(runtimeStyle.offsetLeft)+document." + $viewport + ".scrollLeft)||0");
1771      }
1772    };
1773
1774    util.setOffsetLeft = function(element) {
1775      var propertyName = _isFixed(element) ? "backgroundPositionX" : "offsetLeft";
1776      element.runtimeStyle[propertyName] =
1777        util.getOffsetLeft(element, element.style.backgroundPositionX) -
1778        element.getBoundingClientRect().left - element.clientLeft + 2;
1779    };
1780
1781    util.getOffsetLeft = function(element, position) {
1782      switch (position) {
1783        case "left":
1784        case "top":
1785          return 0;
1786        case "right":
1787        case "bottom":
1788          return viewport.clientWidth - _tmp.offsetWidth;
1789        case "center":
1790          return (viewport.clientWidth - _tmp.offsetWidth) / 2;
1791        default:
1792          if (PERCENT.test(position)) {
1793            return parseInt((viewport.clientWidth - _tmp.offsetWidth) * parseFloat(position) / 100);
1794          }
1795          _tmp.style.left = position;
1796          return _tmp.offsetLeft;
1797      }
1798    };
1799
1800    util.clipWidth = function(element) {
1801      var fixWidth = element.runtimeStyle.fixWidth;
1802      element.runtimeStyle.borderRightWidth = "";
1803      element.runtimeStyle.width = fixWidth ? util.getPixelWidth(element, fixWidth) + "px" : "";
1804      if (element.currentStyle.width !== "auto") {
1805        var rect = element.getBoundingClientRect();
1806        var width = element.offsetWidth - viewport.clientWidth + rect.left - 2;
1807        if (width >= 0) {
1808          element.runtimeStyle.borderRightWidth = "0px";
1809          width = Math.max(getPixelValue(element, element.currentStyle.width) - width, 0);
1810          setOverrideStyle(element, "width",  width);
1811          return width;
1812        }
1813      }
1814    };
1815
1816    util.positionLeft = function(element, recalc) {
1817      // if the element's width is in % units then it must be recalculated
1818      //  with respect to the viewport
1819      if (!recalc && PERCENT.test(element.currentStyle.width)) {
1820        element.runtimeStyle.fixWidth = element.currentStyle.width;
1821      }
1822      if (element.runtimeStyle.fixWidth) {
1823        element.runtimeStyle.width = util.getPixelWidth(element, element.runtimeStyle.fixWidth);
1824      }
1825      //if (recalc) {
1826      //  // if the element is fixed on the right then no need to recalculate
1827      //  if (!element.runtimeStyle.autoLeft) return;
1828      //} else {
1829        element.runtimeStyle.shiftLeft = 0;
1830        element.runtimeStyle._left = element.currentStyle.left;
1831        // is the element fixed on the right?
1832        element.runtimeStyle.autoLeft = element.currentStyle.right !== "auto" && element.currentStyle.left === "auto";
1833      //}
1834      // reset the element's "left" value and get it's natural position
1835      element.runtimeStyle.left = "";
1836      element.runtimeStyle.screenLeft = util.getScreenLeft(element);
1837      element.runtimeStyle.pixelLeft = element.runtimeStyle.screenLeft;
1838      // if the element is contained by another fixed element then there is no need to
1839      //  continually recalculate it's left position
1840      if (!recalc && !_isFixed(element.offsetParent)) {
1841        // onsrcoll produces jerky movement, so we use an expression
1842        _setExpression(element, "pixelLeft", "runtimeStyle.screenLeft+runtimeStyle.shiftLeft+document." + $viewport + ".scrollLeft");
1843      }
1844    };
1845
1846    // I've forgotten how this works...
1847    util.getScreenLeft = function(element) { // thanks to kevin newman (captainn)
1848      var screenLeft = element.offsetLeft, nested = 1;
1849      if (element.runtimeStyle.autoLeft) {
1850        screenLeft = viewport.clientWidth - element.offsetWidth - util.getPixelWidth(element, element.currentStyle.right);
1851      }
1852      // accommodate margins
1853      if (element.currentStyle.marginLeft !== "auto") {
1854        screenLeft -= util.getPixelWidth(element, element.currentStyle.marginLeft);
1855      }
1856      while (element = element.offsetParent) {
1857        if (element.currentStyle.position !== "static") nested = -1;
1858        screenLeft += element.offsetLeft * nested;
1859      }
1860      return screenLeft;
1861    };
1862
1863    util.getPixelWidth = function(element, value) {
1864      return PERCENT.test(value) ? parseInt(parseFloat(value) / 100 * viewport.clientWidth) : getPixelValue(element, value);
1865    };
1866  };
1867  eval("var _vertical=" + rotate(_horizontal));
1868  _horizontal(util);
1869  _vertical(util);
1870})();
1871
1872// =========================================================================
1873// ie7-oveflow.js
1874// =========================================================================
1875
1876/* ---------------------------------------------------------------------
1877
1878  This module alters the structure of the document.
1879  It may adversely affect other CSS rules. Be warned.
1880
1881--------------------------------------------------------------------- */
1882
1883if (appVersion < 7) {
1884  var WRAPPER_STYLE = {
1885    backgroundColor: "transparent",
1886    backgroundImage: "none",
1887    backgroundPositionX: null,
1888    backgroundPositionY: null,
1889    backgroundRepeat: null,
1890    borderTopWidth: 0,
1891    borderRightWidth: 0,
1892    borderBottomWidth: 0,
1893    borderLeftStyle: "none",
1894    borderTopStyle: "none",
1895    borderRightStyle: "none",
1896    borderBottomStyle: "none",
1897    borderLeftWidth: 0,
1898    borderLeftColor: "#000",
1899    borderTopColor: "#000",
1900    borderRightColor: "#000",
1901    borderBottomColor: "#000",
1902    height: null,
1903    marginTop: 0,
1904    marginBottom: 0,
1905    marginRight: 0,
1906    marginLeft: 0,
1907    width: "100%"
1908  };
1909
1910  IE7.CSS.addRecalc("overflow", "visible", function(element) {
1911    if (element.currentStyle.position === "absolute") return;
1912   
1913    // don't do this again
1914    if (element.parentNode.ie7_wrapped) return;
1915
1916    // if max-height is applied, makes sure it gets applied first
1917    if (IE7.Layout && element.currentStyle["max-height"] !== "auto") {
1918      IE7.Layout.maxHeight(element);
1919    }
1920
1921    if (element.currentStyle.marginLeft === "auto") element.style.marginLeft = 0;
1922    if (element.currentStyle.marginRight === "auto") element.style.marginRight = 0;
1923
1924    var wrapper = document.createElement(ANON);
1925    wrapper.ie7_wrapped = element;
1926    for (var propertyName in WRAPPER_STYLE) {
1927      wrapper.style[propertyName] = element.currentStyle[propertyName];
1928      if (WRAPPER_STYLE[propertyName] != null) {
1929        element.runtimeStyle[propertyName] = WRAPPER_STYLE[propertyName];
1930      }
1931    }
1932    wrapper.style.display = "block";
1933    wrapper.style.position = "relative";
1934    element.runtimeStyle.position = "absolute";
1935    element.parentNode.insertBefore(wrapper, element);
1936    wrapper.appendChild(element);
1937  });
1938}
1939
1940// =========================================================================
1941// ie7-quirks.js
1942// =========================================================================
1943
1944function ie7Quirks() {
1945  var FONT_SIZES = "xx-small,x-small,small,medium,large,x-large,xx-large".split(",");
1946  for (var i = 0; i < FONT_SIZES.length; i++) {
1947    FONT_SIZES[FONT_SIZES[i]] = FONT_SIZES[i - 1] || "0.67em";
1948  }
1949 
1950  IE7.CSS.addFix(/(font(-size)?\s*:\s*)([\w.-]+)/, function(match, label, size, value) {
1951    return label + (FONT_SIZES[value] || value);
1952  });
1953 
1954  var NEGATIVE = /^\-/, LENGTH = /(em|ex)$/i;
1955  var EM = /em$/i, EX = /ex$/i;
1956
1957  getPixelValue = function(element, value) {
1958    if (PIXEL.test(value)) return parseInt(value)||0;
1959    var scale = NEGATIVE.test(value)? -1 : 1;
1960    if (LENGTH.test(value)) scale *= getFontScale(element);
1961    temp.style.width = scale < 0 ? value.slice(1) : value;
1962    body.appendChild(temp);
1963    // retrieve pixel width
1964    value = scale * temp.offsetWidth;
1965    // remove the temporary element
1966    temp.removeNode();
1967    return parseInt(value);
1968  };
1969
1970  var temp = createTempElement();
1971  function getFontScale(element) {
1972    var scale = 1;
1973    temp.style.fontFamily = element.currentStyle.fontFamily;
1974    temp.style.lineHeight = element.currentStyle.lineHeight;
1975    //temp.style.fontSize = "";
1976    while (element != body) {
1977      var fontSize = element.currentStyle["ie7-font-size"];
1978      if (fontSize) {
1979        if (EM.test(fontSize)) scale *= parseFloat(fontSize);
1980        else if (PERCENT.test(fontSize)) scale *= (parseFloat(fontSize) / 100);
1981        else if (EX.test(fontSize)) scale *= (parseFloat(fontSize) / 2);
1982        else {
1983          temp.style.fontSize = fontSize;
1984          return 1;
1985        }
1986      }
1987      element = element.parentElement;
1988    }
1989    return scale;
1990  };
1991
1992  // cursor:pointer (IE5.x)
1993  IE7.CSS.addFix(/cursor\s*:\s*pointer/, "cursor:hand");
1994  // display:list-item (IE5.x)
1995  IE7.CSS.addFix(/display\s*:\s*list-item/, "display:block");
1996 
1997  // -----------------------------------------------------------------------
1998  //  margin:auto
1999  // -----------------------------------------------------------------------
2000 
2001  function fixMargin(element) {
2002    var parent = element.parentElement;
2003    var margin = parent.offsetWidth - element.offsetWidth - getPaddingWidth(parent);
2004    var autoRight = (element.currentStyle["ie7-margin"] && element.currentStyle.marginRight === "auto") ||
2005      element.currentStyle["ie7-margin-right"] === "auto";
2006    switch (parent.currentStyle.textAlign) {
2007      case "right":
2008        margin = autoRight ? parseInt(margin / 2) : 0;
2009        element.runtimeStyle.marginRight = margin + "px";
2010        break;
2011      case "center":
2012        if (autoRight) margin = 0;
2013      default:
2014        if (autoRight) margin /= 2;
2015        element.runtimeStyle.marginLeft = parseInt(margin) + "px";
2016    }
2017  };
2018
2019  function getPaddingWidth(element) {
2020    return getPixelValue(element, element.currentStyle.paddingLeft) +
2021      getPixelValue(element, element.currentStyle.paddingRight);
2022  };
2023 
2024  IE7.CSS.addRecalc("margin(-left|-right)?", "[^};]*auto", function(element) {
2025    if (register(fixMargin, element,
2026      element.parentElement &&
2027      element.currentStyle.display === "block" &&
2028      element.currentStyle.marginLeft === "auto" &&
2029      element.currentStyle.position !== "absolute")) {
2030        fixMargin(element);
2031    }
2032  });
2033 
2034  addResize(function() {
2035    for (var i in fixMargin.elements) {
2036      var element = fixMargin.elements[i];
2037      element.runtimeStyle.marginLeft =
2038      element.runtimeStyle.marginRight = "";
2039      fixMargin(element);
2040    }
2041  });
2042};
2043
2044
2045// =========================================================================
2046// ie8-css.js
2047// =========================================================================
2048
2049var BRACKETS = "\\([^)]+\\)";
2050
2051// pseudo-elements can be declared with a double colon
2052encoder.add(/::(before|after)/, ":$1");
2053
2054if (appVersion < 8) {
2055
2056  if (IE7.CSS.pseudoClasses) IE7.CSS.pseudoClasses += "|";
2057  IE7.CSS.pseudoClasses += "before|after|lang" + BRACKETS;
2058
2059  // -----------------------------------------------------------------------
2060  // propertyName: inherit;
2061  // -----------------------------------------------------------------------
2062 
2063  function parseInherited(cssText) {
2064    return cssText.replace(new RegExp("([{;\\s])(" + inheritedProperties.join("|") + ")\\s*:\\s*([^;}]+)", "g"), "$1$2:$3;ie7-$2:$3");
2065  };
2066
2067  var INHERITED = /[\w-]+\s*:\s*inherit/g;
2068  var STRIP_IE7_FLAGS = /ie7\-|\s*:\s*inherit/g;
2069  var DASH_LOWER = /\-([a-z])/g;
2070  function toUpper(match, chr) {return chr.toUpperCase()};
2071 
2072  IE7.CSS.addRecalc("[\\w-]+", "inherit", function(element, cssText) {
2073    if (element.parentElement) {
2074      var inherited = cssText.match(INHERITED);
2075      for (var i = 0; i < inherited.length; i++) {
2076        var propertyName = inherited[i].replace(STRIP_IE7_FLAGS, "");
2077        if (element.currentStyle["ie7-" + propertyName] === "inherit") {
2078          propertyName = propertyName.replace(DASH_LOWER, toUpper);
2079          element.runtimeStyle[propertyName] = element.parentElement.currentStyle[propertyName];
2080        }
2081      }
2082    }
2083  }, function(match) {
2084    inheritedProperties.push(rescape(match.slice(1).split(":")[0]));
2085    return match;
2086  });
2087
2088  // -----------------------------------------------------------------------
2089  // dynamic pseudo-classes
2090  // -----------------------------------------------------------------------
2091
2092  var Focus = new DynamicPseudoClass("focus", function(element) {
2093    var instance = arguments;
2094
2095    IE7.CSS.addEventHandler(element, "onfocus", function() {
2096      Focus.unregister(instance); // in case it starts with focus
2097      Focus.register(instance);
2098    });
2099
2100    IE7.CSS.addEventHandler(element, "onblur", function() {
2101      Focus.unregister(instance);
2102    });
2103
2104    // check the active element for initial state
2105    if (element == document.activeElement) {
2106      Focus.register(instance)
2107    }
2108  });
2109
2110  var Active = new DynamicPseudoClass("active", function(element) {
2111    var instance = arguments;
2112    IE7.CSS.addEventHandler(element, "onmousedown", function() {
2113      Active.register(instance);
2114    });
2115  });
2116
2117  // globally trap the mouseup event (thanks Martijn!)
2118  addEventHandler(document, "onmouseup", function() {
2119    var instances = Active.instances;
2120    for (var i in instances) Active.unregister(instances[i]);
2121  });
2122
2123  // -----------------------------------------------------------------------
2124  // IE7 pseudo elements
2125  // -----------------------------------------------------------------------
2126
2127  // constants
2128  var URL = /^url\s*\(\s*([^)]*)\)$/;
2129  var POSITION_MAP = {
2130    before0: "beforeBegin",
2131    before1: "afterBegin",
2132    after0: "afterEnd",
2133    after1: "beforeEnd"
2134  };
2135
2136  var PseudoElement = IE7.PseudoElement = Rule.extend({
2137    constructor: function(selector, position, cssText) {
2138      // initialise object properties
2139      this.position = position;
2140      var content = cssText.match(PseudoElement.CONTENT), match, entity;
2141      if (content) {
2142        content = content[1];
2143        match = content.split(/\s+/);
2144        for (var i = 0; (entity = match[i]); i++) {
2145          match[i] = /^attr/.test(entity) ? {attr: entity.slice(5, -1)} :
2146            entity.charAt(0) === "'" ? getString(entity) : decode(entity);
2147        }
2148        content = match;
2149      }
2150      this.content = content;
2151      // CSS text needs to be decoded immediately
2152      this.base(selector, decode(cssText));
2153    },
2154
2155    init: function() {
2156      // execute the underlying css query for this class
2157      this.match = cssQuery(this.selector);
2158      for (var i = 0; i < this.match.length; i++) {
2159        var runtimeStyle = this.match[i].runtimeStyle;
2160        if (!runtimeStyle[this.position]) runtimeStyle[this.position] = {cssText:""};
2161        runtimeStyle[this.position].cssText += ";" + this.cssText;
2162        if (this.content != null) runtimeStyle[this.position].content = this.content;
2163      }
2164    },
2165
2166    create: function(target) {
2167      var generated = target.runtimeStyle[this.position];
2168      if (generated) {
2169        // copy the array of values
2170        var content = [].concat(generated.content || "");
2171        for (var j = 0; j < content.length; j++) {
2172          if (typeof content[j] == "object") {
2173            content[j] = target.getAttribute(content[j].attr);
2174          }
2175        }
2176        content = content.join("");
2177        var url = content.match(URL);
2178        var cssText = "overflow:hidden;" + generated.cssText.replace(/'/g, '"');
2179        var position = POSITION_MAP[this.position + Number(target.canHaveChildren)];
2180        var id = 'ie7_pseudo' + PseudoElement.count++;
2181        target.insertAdjacentHTML(position, format(PseudoElement.ANON, this.className, id, cssText, url ? "" : content));
2182        if (url) {
2183          var src = getString(url[1]);
2184          var pseudoElement = document.getElementById(id);
2185          pseudoElement.src = src;
2186          addFilter(pseudoElement, "crop");
2187          var targetIsFloated = target.currentStyle.styleFloat !== "none";
2188          if (pseudoElement.currentStyle.display === "inline" || targetIsFloated) {
2189            if (appVersion < 7 && targetIsFloated && target.canHaveChildren) {
2190              target.runtimeStyle.display = "inline";
2191              target.runtimeStyle.position = "relative";
2192              pseudoElement.runtimeStyle.position = "absolute";
2193            }
2194            pseudoElement.style.display = "inline-block";
2195            if (target.currentStyle.styleFloat !== "none") {
2196              pseudoElement.style.pixelWidth = target.offsetWidth;
2197            }
2198            var image = new Image;
2199            image.onload = function() {
2200              pseudoElement.style.pixelWidth = this.width;
2201              pseudoElement.style.pixelHeight = Math.max(this.height, pseudoElement.offsetHeight);
2202            };
2203            image.src = src;
2204          }
2205        }
2206        target.runtimeStyle[this.position] = null;
2207      }
2208    },
2209
2210    recalc: function() {
2211      if (this.content == null) return;
2212      for (var i = 0; i < this.match.length; i++) {
2213        this.create(this.match[i]);
2214      }
2215    },
2216
2217    toString: function() {
2218      return "." + this.className + "{display:inline}";
2219    }
2220  }, {
2221    CONTENT: /content\s*:\s*([^;]*)(;|$)/,
2222    ANON: "<ie7:! class='ie7_anon %1' id=%2 style='%3'>%4</ie7:!>",
2223    MATCH: /(.*):(before|after).*/,
2224
2225    count: 0
2226  });
2227
2228  IE7._getLang = function(element) {
2229    var lang = "";
2230    while (element && element.nodeType === 1) {
2231      lang = element.lang || element.getAttribute("lang") || "";
2232      if (lang) break;
2233      element = element.parentNode;
2234    }
2235    return lang;
2236  };
2237
2238  FILTER = extend(FILTER, {
2239    ":lang\\(([^)]+)\\)":    "((ii=IE7._getLang(e))==='$1'||ii.indexOf('$1-')===0)&&"
2240  });
2241}
2242
2243// =========================================================================
2244// ie8-html.js
2245// =========================================================================
2246
2247var UNSUCCESSFUL = /^(submit|reset|button)$/;
2248
2249// -----------------------------------------------------------------------
2250// <button>
2251// -----------------------------------------------------------------------
2252
2253// IE bug means that innerText is submitted instead of "value"
2254IE7.HTML.addRecalc("button,input", function(button) {
2255  if (button.nodeName === "BUTTON") {
2256    var match = button.outerHTML.match(/ value="([^"]*)"/i);
2257    button.runtimeStyle.value = match ? match[1] : "";
2258  }
2259  // flag the button/input that was used to submit the form
2260  if (button.type === "submit") {
2261    addEventHandler(button, "onclick", function() {
2262      button.runtimeStyle.clicked = true;
2263      setTimeout("document.all." + button.uniqueID + ".runtimeStyle.clicked=false", 1);
2264    });
2265  }
2266});
2267
2268// -----------------------------------------------------------------------
2269// <form>
2270// -----------------------------------------------------------------------
2271
2272// only submit "successful controls
2273IE7.HTML.addRecalc("form", function(form) {
2274  addEventHandler(form, "onsubmit", function() {
2275    for (var element, i = 0; element = form[i]; i++) {
2276      if (UNSUCCESSFUL.test(element.type) && !element.disabled && !element.runtimeStyle.clicked) {
2277        element.disabled = true;
2278        setTimeout("document.all." + element.uniqueID + ".disabled=false", 1);
2279      } else if (element.nodeName === "BUTTON" && element.type === "submit") {
2280        setTimeout("document.all." + element.uniqueID + ".value='" + element.value + "'", 1);
2281        element.value = element.runtimeStyle.value;
2282      }
2283    }
2284  });
2285});
2286
2287// -----------------------------------------------------------------------
2288// <img>
2289// -----------------------------------------------------------------------
2290
2291// get rid of the spurious tooltip produced by the alt attribute on images
2292IE7.HTML.addRecalc("img", function(img) {
2293  if (img.alt && !img.title) img.title = "";
2294});
2295
2296// =========================================================================
2297// ie8-layout.js
2298// =========================================================================
2299
2300if (appVersion < 8) {
2301  IE7.CSS.addRecalc("border-spacing", NUMERIC, function(element) {
2302    if (element.currentStyle.borderCollapse !== "collapse") {
2303      element.cellSpacing = getPixelValue(element, element.currentStyle["ie7-border-spacing"].split(" ")[0]);
2304    }
2305  });
2306  IE7.CSS.addRecalc("box-sizing", "content-box", IE7.Layout.boxSizing);
2307  IE7.CSS.addRecalc("box-sizing", "border-box", IE7.Layout.borderBox);
2308}
2309
2310// =========================================================================
2311// ie8-graphics.js
2312// =========================================================================
2313
2314if (appVersion < 8) {
2315  // fix object[type=image/*]
2316  var IMAGE = /^image/i;
2317  IE7.HTML.addRecalc("object", function(element) {
2318    if (IMAGE.test(element.type)) {
2319      element.body.style.cssText = "margin:0;padding:0;border:none;overflow:hidden";
2320      return element;
2321    }
2322  });
2323}
2324
2325// =========================================================================
2326// ie9-css.js
2327// =========================================================================
2328
2329var NOT_NEXT_BY_TYPE     = "!IE7._getElementSiblingByType(e,'next')&&",
2330    NOT_PREVIOUS_BY_TYPE = NOT_NEXT_BY_TYPE.replace("next", "previous");
2331
2332if (IE7.CSS.pseudoClasses) IE7.CSS.pseudoClasses += "|";
2333IE7.CSS.pseudoClasses += "(?:first|last|only)\\-(?:child|of\\-type)|empty|root|target|" +
2334  ("not|nth\\-child|nth\\-last\\-child|nth\\-of\\-type|nth\\-last\\-of\\-type".split("|").join(BRACKETS + "|") + BRACKETS);
2335 
2336// :checked
2337var Checked = new DynamicPseudoClass("checked", function(element) {
2338  if (typeof element.checked !== "boolean") return;
2339  var instance = arguments;
2340  IE7.CSS.addEventHandler(element, "onpropertychange", function() {
2341    if (event.propertyName === "checked") {
2342      if (element.checked === true) Checked.register(instance);
2343      else Checked.unregister(instance);
2344    }
2345  });
2346  // check current checked state
2347  if (element.checked === true) Checked.register(instance);
2348});
2349
2350// :enabled
2351var Enabled = new DynamicPseudoClass("enabled", function(element) {
2352  if (typeof element.disabled !== "boolean") return;
2353  var instance = arguments;
2354  IE7.CSS.addEventHandler(element, "onpropertychange", function() {
2355    if (event.propertyName === "disabled") {
2356      if (element.disabled === false) Enabled.register(instance);
2357      else Enabled.unregister(instance);
2358    }
2359  });
2360  // check current disabled state
2361  if (element.disabled === false) Enabled.register(instance);
2362});
2363
2364// :disabled
2365var Disabled = new DynamicPseudoClass("disabled", function(element) {
2366  if (typeof element.disabled !== "boolean") return;
2367  var instance = arguments;
2368  IE7.CSS.addEventHandler(element, "onpropertychange", function() {
2369    if (event.propertyName === "disabled") {
2370      if (element.disabled === true) Disabled.register(instance);
2371      else Disabled.unregister(instance);
2372    }
2373  });
2374  // check current disabled state
2375  if (element.disabled === true) Disabled.register(instance);
2376});
2377
2378// :indeterminate (Kevin Newman)
2379var Indeterminate = new DynamicPseudoClass("indeterminate", function(element) {
2380  if (typeof element.indeterminate !== "boolean") return;
2381  var instance = arguments;
2382  IE7.CSS.addEventHandler(element, "onpropertychange", function() {
2383    if (event.propertyName === "indeterminate") {
2384      if (element.indeterminate === true) Indeterminate.register(instance);
2385      else Indeterminate.unregister(instance);
2386    }
2387  });
2388  IE7.CSS.addEventHandler(element, "onclick", function() {
2389    Indeterminate.unregister(instance);
2390  });
2391  // clever Kev says no need to check this up front
2392});
2393
2394// :target
2395var Target = new DynamicPseudoClass("target", function(element) {
2396  var instance = arguments;
2397  // if an element has a tabIndex then it can become "active".
2398  //  The default is zero anyway but it works...
2399  if (!element.tabIndex) element.tabIndex = 0;
2400  // this doesn't detect the back button. I don't know how to do that without adding an iframe :-(
2401  IE7.CSS.addEventHandler(document, "onpropertychange", function() {
2402    if (event.propertyName === "activeElement") {
2403      if (element.id && element.id === location.hash.slice(1)) Target.register(instance);
2404      else Target.unregister(instance);
2405    }
2406  });
2407  // check the current location
2408  if (element.id && element.id === location.hash.slice(1)) Target.register(instance);
2409});
2410
2411// Register a node and index its siblings.
2412var _currentIndex = 1, // -@DRE
2413    allIndexes = {_currentIndex: 1};
2414
2415IE7._indexOf = function(element, last, ofType) {
2416  var parent = element.parentNode;
2417  if (!parent || parent.nodeType !== 1) return NaN;
2418
2419  var tagName = ofType ? element.nodeName : "";
2420  if (tagName === "TR" && element.sectionRowIndex >= 0) {
2421    var index = element.sectionRowIndex;
2422    return last ? element.parentNode.rows.length - index + 1 : index;
2423  }
2424  if ((tagName === "TD" || tagName === "TH") && element.cellIndex >= 0) {
2425    index = element.cellIndex;
2426    return last ? element.parentNode.cells.length - index + 1 : index;
2427  }
2428  if (allIndexes._currentIndex !== _currentIndex) {
2429    allIndexes = {_currentIndex: _currentIndex};
2430  }
2431  var id = (parent.uniqueID) + "-" + tagName,
2432      indexes = allIndexes[id];
2433  if (!indexes) {
2434    indexes = {};
2435    var index = 0,
2436        child = parent.firstChild;
2437    while (child) {
2438      if (ofType ? child.nodeName === tagName : child.nodeName > "@") {
2439        indexes[child.uniqueID] = ++index;
2440      }
2441      child = child.nextSibling;
2442    }
2443    indexes.length = index;
2444    allIndexes[id] = indexes;
2445  }
2446  index = indexes[element.uniqueID];
2447  return last ? indexes.length - index + 1 : index;
2448};
2449
2450IE7._isEmpty = function(node) {
2451  node = node.firstChild;
2452  while (node) {
2453    if (node.nodeType === 3 || node.nodeName > "@") return false;
2454    node = node.nextSibling;
2455  }
2456  return true;
2457};
2458
2459IE7._getElementSiblingByType = function(node, direction) {
2460  var tagName = node.nodeName;
2461  direction += "Sibling";
2462  do {
2463    node = node[direction];
2464    if (node && node.nodeName === tagName) break;
2465  } while (node);
2466  return node;
2467};
2468
2469var ONE = {"+": 1, "-": -1}, SPACES = / /g;
2470
2471FILTER = extend(extend({
2472  ":nth(-last)?-(?:child|(of-type))\\((<#nth_arg>)\\)(<#filter>)?": function(match, last, ofType, args, filters) { // :nth- pseudo classes
2473    args = args.replace(SPACES, "");
2474
2475    var index = "IE7._indexOf(e," + !!last + "," + !!ofType + ")";
2476
2477    if (args === "even") args = "2n";
2478    else if (args === "odd") args = "2n+1";
2479    else if (!isNaN(args)) args = "0n" + ~~args;
2480
2481    args = args.split("n");
2482    var a = ~~(ONE[args[0]] || args[0] || 1),
2483        b = ~~args[1];
2484    if (a === 0) {
2485      var expr = index + "===" + b;
2486    } else {
2487      expr = "((ii=" + index + ")-(" + b + "))%" + a + "===0&&ii" + (a < 0 ? "<" : ">") + "=" + b;
2488    }
2489    return this.parse(filters) + expr + "&&";
2490  },
2491
2492  "<#negation>": function(match, simple) {
2493    if (/:not/i.test(simple)) throwSelectorError();
2494
2495    if (/^[#.:\[]/.test(simple)) {
2496      simple = "*" + simple;
2497    }
2498    return "!(" + MATCHER.parse(simple).slice(3, -2) + ")&&";
2499  }
2500}, FILTER), {
2501  ":checked":         "e.checked===true&&",
2502  ":disabled":        "e.disabled===true&&",
2503  ":enabled":         "e.disabled===false&&",
2504  ":last-child":      "!" + NEXT_SIBLING + "&&",
2505  ":only-child":      "!" + PREVIOUS_SIBLING + "&&!" + NEXT_SIBLING + "&&",
2506  ":first-of-type":   NOT_PREVIOUS_BY_TYPE,
2507  ":last-of-type":    NOT_NEXT_BY_TYPE,
2508  ":only-of-type":    NOT_PREVIOUS_BY_TYPE + NOT_NEXT_BY_TYPE,
2509
2510  ":empty":          "IE7._isEmpty(e)&&",
2511  ":root":           "e==R&&",
2512  ":target":         "H&&" + ID_ATTRIBUTE + "===H&&"
2513});
2514
2515var HTML5 = "article,aside,audio,canvas,details,figcaption,figure,footer,header,hgroup,mark,menu,meter,nav,output,progress,section,summary,time,video".split(",");
2516for (var i = 0, tagName; tagName = HTML5[i]; i++) document.createElement(tagName);
2517
2518HEADER += "datalist{display:none}\
2519details{padding-left:40px;display:block;margin:1em 0}\
2520meter,progress{vertical-align:-0.2em;width:5em;height:1em;display:inline-block}\
2521progress{width:10em;}\
2522article,aside,figcaption,footer,header,hgroup,summary,section,nav{display:block;margin:1em 0}\
2523figure{margin:1em 40px;display:block}\
2524mark{background:yellow}";
2525
2526// =========================================================================
2527// ie9-layout.js
2528// =========================================================================
2529
2530// =========================================================================
2531// ie9-graphics.js
2532// =========================================================================
2533
2534IE7.CSS.addFix(/\bopacity\s*:\s*([\d.]+)/, function(match, value) {
2535  return "zoom:1;filter:Alpha(opacity=" + ((value * 100) || 1) + ")";
2536});
2537
2538var MATCHER;
2539
2540var cssQuery = (function() {
2541  var CONTEXT = /^[>+~]/;
2542 
2543  var useContext = false;
2544 
2545  // This is not a selector engine in the strictest sense. So it's best to silently error.
2546  function cssQuery(selector, context, single) {
2547    selector = trim(selector);
2548    if (!context) context = document;
2549    var ref = context;
2550    useContext = CONTEXT.test(selector);
2551    if (useContext) {
2552      context = context.parentNode;
2553      selector = "*" + selector;
2554    }
2555    try {
2556      return selectQuery.create(selector, useContext)(context, single ? null : [], ref);
2557    } catch (ex) {
2558      return single ? null : [];
2559    }
2560  };
2561
2562  var VALID_SELECTOR = /^(\\.|[' >+~#.\[\]:*(),\w-\^|$=]|[^\x00-\xa0])+$/;
2563
2564  var _EVALUATED = /^(href|src)$/;
2565  var _ATTRIBUTES = {
2566    "class": "className",
2567    "for": "htmlFor"
2568  };
2569
2570  var IE7_CLASS_NAMES = /\sie7_\w+/g;
2571
2572  var USE_IFLAG = /^(action|cite|codebase|data|dynsrc|href|longdesc|lowsrc|src|usemap|url)$/i;
2573
2574  IE7._getAttribute = function(element, name) {
2575    if (element.getAttributeNode) {
2576      var attribute = element.getAttributeNode(name);
2577    }
2578    name = _ATTRIBUTES[name.toLowerCase()] || name;
2579    if (!attribute) attribute = element.attributes[name];
2580    var specified = attribute && attribute.specified;
2581
2582    if (element[name] && typeof element[name] == "boolean") return name.toLowerCase();
2583    if ((specified && USE_IFLAG.test(name)) || (!attribute && MSIE5) || name === "value" || name === "type") {
2584      return element.getAttribute(name, 2);
2585    }
2586    if (name === "style") return element.style.cssText.toLowerCase() || null;
2587
2588    return specified ? String(attribute.nodeValue) : null;
2589  };
2590
2591  var names = "colSpan,rowSpan,vAlign,dateTime,accessKey,tabIndex,encType,maxLength,readOnly,longDesc";
2592  // Convert the list of strings to a hash, mapping the lowercase name to the camelCase name.
2593  extend(_ATTRIBUTES, combine(names.toLowerCase().split(","), names.split(",")));
2594
2595  IE7._getElementSibling = function(node, direction) {
2596    direction += "Sibling";
2597    do {
2598      node = node[direction];
2599      if (node && node.nodeName > "@") break;
2600    } while (node);
2601    return node;
2602  };
2603
2604  var IMPLIED_ASTERISK    = /(^|[, >+~])([#.:\[])/g,
2605      BLOCKS              = /\)\{/g,
2606      COMMA               = /,/,
2607      QUOTED              = /^['"]/,
2608      HEX_ESCAPE          = /\\([\da-f]{2,2})/gi,
2609      LAST_CHILD          = /last/i;
2610
2611  IE7._byId = function(document, id) {
2612    var result = document.all[id] || null;
2613    // Returns a single element or a collection.
2614    if (!result || (result.nodeType && IE7._getAttribute(result, "id") === id)) return result;
2615    // document.all has returned a collection of elements with name/id
2616    for (var i = 0; i < result.length; i++) {
2617      if (IE7._getAttribute(result[i], "id") === id) return result[i];
2618    }
2619    return null;
2620  };
2621
2622  // =========================================================================
2623  // dom/selectors-api/CSSSelectorParser.js
2624  // =========================================================================
2625
2626  // http://www.w3.org/TR/css3-selectors/#w3cselgrammar (kinda)
2627  var CSSSelectorParser = RegGrp.extend({
2628    dictionary: new Dictionary({
2629      ident:           /\-?(\\.|[_a-z]|[^\x00-\xa0])(\\.|[\w-]|[^\x00-\xa0])*/,
2630      combinator:      /[\s>+~]/,
2631      operator:        /[\^~|$*]?=/,
2632      nth_arg:         /[+-]?\d+|[+-]?\d*n(?:\s*[+-]\s*\d+)?|even|odd/,
2633      tag:             /\*|<#ident>/,
2634      id:              /#(<#ident>)/,
2635      'class':         /\.(<#ident>)/,
2636      pseudo:          /\:([\w-]+)(?:\(([^)]+)\))?/,
2637      attr:            /\[(<#ident>)(?:(<#operator>)((?:\\.|[^\[\]#.:])+))?\]/,
2638      negation:        /:not\((<#tag>|<#id>|<#class>|<#attr>|<#pseudo>)\)/,
2639      sequence:        /(\\.|[~*]=|\+\d|\+?\d*n\s*\+\s*\d|[^\s>+~,\*])+/,
2640      filter:          /[#.:\[]<#sequence>/,
2641      selector:        /[^>+~](\\.|[^,])*?/,
2642      grammar:         /^(<#selector>)((,<#selector>)*)$/
2643    }),
2644
2645    ignoreCase: true
2646  });
2647
2648  var normalizer = new CSSSelectorParser({
2649    "\\\\.|[~*]\\s+=|\\+\\s+\\d": RegGrp.IGNORE,
2650    "\\[\\s+": "[",
2651    "\\(\\s+": "(",
2652    "\\s+\\)": ")",
2653    "\\s+\\]": "]",
2654    "\\s*([,>+~]|<#operator>)\\s*": "$1",
2655    "\\s+$": "",
2656    "\\s+": " "
2657  });
2658
2659  function normalize(selector) {
2660    selector = normalizer.parse(selector.replace(HEX_ESCAPE, "\\x$1"))
2661      .replace(UNESCAPE, "$1")
2662      .replace(IMPLIED_ASTERISK, "$1*$2");
2663    if (!VALID_SELECTOR.test(selector)) throwSelectorError();
2664    return selector;
2665  };
2666
2667  function unescape(query) {
2668    // put string values back
2669    return query.replace(ESCAPED, unescapeString);
2670  };
2671
2672  function unescapeString(match, index) {
2673    return strings[index];
2674  };
2675
2676  var BRACES = /\{/g, BRACES_ESCAPED = /\\{/g;
2677
2678  function closeBlock(group) {
2679    return Array((group.replace(BRACES_ESCAPED, "").match(BRACES) || "").length + 1).join("}");
2680  };
2681
2682  FILTER = new CSSSelectorParser(FILTER);
2683
2684  var TARGET = /:target/i, ROOT = /:root/i;
2685
2686  function getConstants(selector) {
2687    var constants = "";
2688    if (ROOT.test(selector)) constants += ",R=d.documentElement";
2689    if (TARGET.test(selector)) constants += ",H=d.location;H=H&&H.hash.replace('#','')";
2690    if (constants || selector.indexOf("#") !== -1) {
2691      constants = ",t=c.nodeType,d=t===9?c:c.ownerDocument||(c.document||c).parentWindow.document" + constants;
2692    }
2693    return "var ii" + constants + ";";
2694  };
2695
2696  var COMBINATOR = {
2697    " ":   ";while(e!=s&&(e=e.parentNode)&&e.nodeType===1){",
2698    ">":   ".parentElement;if(e){",
2699    "+":   ";while((e=e.previousSibling)&&!(" + IS_ELEMENT + "))continue;if(e){",
2700    "~":   ";while((e=e.previousSibling)){" + IF_ELEMENT
2701  };
2702
2703  var TOKEN = /\be\b/g;
2704
2705  MATCHER = new CSSSelectorParser({
2706    "(?:(<#selector>)(<#combinator>))?(<#tag>)(<#filter>)?$": function(match, before, combinator, tag, filters) {
2707      var group = "";
2708      if (tag !== "*") {
2709        var TAG = tag.toUpperCase();
2710        group += "if(e.nodeName==='" + TAG + (TAG === tag ? "" : "'||e.nodeName==='" + tag) + "'){";
2711      }
2712      if (filters) {
2713        group += "if(" + FILTER.parse(filters).slice(0, -2) + "){";
2714      }
2715      group = group.replace(TOKEN, "e" + this.index);
2716      if (combinator) {
2717        group += "var e=e" + (this.index++) + COMBINATOR[combinator];
2718        group = group.replace(TOKEN, "e" + this.index);
2719      }
2720      if (before) {
2721        group += this.parse(before);
2722      }
2723      return group;
2724    }
2725  });
2726 
2727  var BY_ID       = "e0=IE7._byId(d,'%1');if(e0){",
2728      BY_TAG_NAME = "var n=c.getElementsByTagName('%1');",
2729      STORE       = "if(r==null)return e0;r[k++]=e0;";
2730
2731  var TAG_NAME = 1;
2732
2733  var SELECTOR = new CSSSelectorParser({
2734    "^((?:<#selector>)?(?:<#combinator>))(<#tag>)(<#filter>)?$": true
2735  });
2736
2737  var cache = {};
2738
2739  var selectById = new CSSSelectorParser({
2740    "^(<#tag>)#(<#ident>)(<#filter>)?( [^,]*)?$": function(match, tagName, id, filters, after) {
2741      var block = format(BY_ID, id), endBlock = "}";
2742      if (filters) {
2743        block += MATCHER.parse(tagName + filters);
2744        endBlock = closeBlock(block);
2745      }
2746      if (after) {
2747        block += "s=c=e0;" + selectQuery.parse("*" + after);
2748      } else {
2749        block += STORE;
2750      }
2751      return block + endBlock;
2752    },
2753
2754    "^([^#,]+)#(<#ident>)(<#filter>)?$": function(match, before, id, filters) {
2755      var block = format(BY_ID, id);
2756      if (before === "*") {
2757        block += STORE;
2758      } else {
2759        block += MATCHER.parse(before + filters) + STORE + "break";
2760      }
2761      return block + closeBlock(block);
2762    },
2763
2764    "^.*$": ""
2765  });
2766
2767  var selectQuery = new CSSSelectorParser({
2768    "<#grammar>": function(match, selector, remainingSelectors) {
2769      if (!this.groups) this.groups = [];
2770
2771      var group = SELECTOR.exec(" " + selector);
2772
2773      if (!group) throwSelectorError();
2774
2775      this.groups.push(group.slice(1));
2776
2777      if (remainingSelectors) {
2778        return this.parse(remainingSelectors.replace(COMMA, ""));
2779      }
2780
2781      var groups = this.groups,
2782          tagName = groups[0][TAG_NAME]; // first tag name
2783
2784      for (var i = 1; group = groups[i]; i++) { // search tag names
2785        if (tagName !== group[TAG_NAME]) {
2786          tagName = "*"; // mixed tag names, so use "*"
2787          break;
2788        }
2789      }
2790
2791      var matcher = "", store = STORE + "continue filtering;";
2792
2793      for (var i = 0; group = groups[i]; i++) {
2794        MATCHER.index = 0;
2795        if (tagName !== "*") group[TAG_NAME] = "*"; // we are already filtering by tagName
2796        group = group.join("");
2797        if (group === " *") { // select all
2798          matcher = store;
2799          break;
2800        } else {
2801          group = MATCHER.parse(group);
2802          if (useContext) group += "if(e" + MATCHER.index + "==s){";
2803          matcher += group + store + closeBlock(group);
2804        }
2805      }
2806
2807      // reduce to a single loop
2808      var isWild = tagName === "*";
2809      return (isWild ? "var n=c.all;" : format(BY_TAG_NAME, tagName)) +
2810        "filtering:while((e0=n[i++]))" +
2811        (isWild ? IF_ELEMENT.replace(TOKEN, "e0") : "{") +
2812          matcher +
2813        "}";
2814    },
2815
2816    "^.*$": throwSelectorError
2817  });
2818
2819  var REDUNDANT_NODETYPE_CHECKS = /\&\&(e\d+)\.nodeType===1(\)\{\s*if\(\1\.nodeName=)/g;
2820
2821  selectQuery.create = function(selector) {
2822    if (!cache[selector]) {
2823      selector = normalize(selector);
2824      this.groups = null;
2825      MATCHER.index = 0;
2826      var block = this.parse(selector);
2827      this.groups = null;
2828      MATCHER.index = 0;
2829      if (selector.indexOf("#") !== -1) {
2830        var byId  = selectById.parse(selector);
2831        if (byId) {
2832          block =
2833            "if(t===1||t===11|!c.getElementById){" +
2834              block +
2835            "}else{" +
2836              byId +
2837            "}";
2838        }
2839      }
2840      // remove redundant nodeType==1 checks
2841      block = block.replace(REDUNDANT_NODETYPE_CHECKS, "$2");
2842      block = getConstants(selector) + decode(block);
2843      cache[selector] = new Function("return function(c,r,s){var i=0,k=0,e0;" + block + "return r}")();
2844    }
2845    return cache[selector];
2846  };
2847
2848  return cssQuery;
2849})();
2850
2851function throwSelectorError() {
2852  throw new SyntaxError("Invalid selector.");
2853};
2854
2855// -----------------------------------------------------------------------
2856// initialisation
2857// -----------------------------------------------------------------------
2858
2859IE7.loaded = true;
2860
2861(function() {
2862  try {
2863    // http://javascript.nwbox.com/IEContentLoaded/
2864    if (!document.body) throw "continue";
2865    documentElement.doScroll("left");
2866  } catch (ex) {
2867    setTimeout(arguments.callee, 1);
2868    return;
2869  }
2870  // execute the inner text of the IE7 script
2871  try {
2872    eval(script.innerHTML);
2873  } catch (ex) {
2874    // ignore errors
2875  }
2876  if (typeof IE7_PNG_SUFFIX == "object") {
2877    PNG = IE7_PNG_SUFFIX;
2878  } else {
2879    PNG = new RegExp(rescape(window.IE7_PNG_SUFFIX || "-trans.png") + "(\\?.*)?$", "i");
2880  }
2881
2882  // frequently used references
2883  body = document.body;
2884  viewport = MSIE5 ? body : documentElement;
2885
2886  // classes
2887  body.className += " ie7_body";
2888  documentElement.className += " ie7_html";
2889
2890  if (MSIE5) ie7Quirks();
2891
2892  IE7.CSS.init();
2893  IE7.HTML.init();
2894
2895  IE7.HTML.apply();
2896  IE7.CSS.apply();
2897
2898  IE7.recalc();
2899})();
2900
2901})(this, document);
Note: See TracBrowser for help on using the repository browser.

Sites map