diff --git a/lib/galaxy/webapps/reports/static/scripts/IE7.js b/lib/galaxy/webapps/reports/static/scripts/IE7.js new file mode 100644 index 00000000000..c02f3756e64 --- /dev/null +++ b/lib/galaxy/webapps/reports/static/scripts/IE7.js @@ -0,0 +1,2205 @@ +// timestamp: Sun, 03 Feb 2008 19:26:22 +/* + IE7/IE8.js - copyright 2004-2008, Dean Edwards + http://dean.edwards.name/IE7/ + http://www.opensource.org/licenses/mit-license.php +*/ + +/* W3C compliance for Microsoft Internet Explorer */ + +/* credits/thanks: + Shaggy, Martijn Wargers, Jimmy Cerra, Mark D Anderson, + Lars Dieckow, Erik Arvidsson, Gellért Gyuris, James Denny, + Unknown W Brackets, Benjamin Westfarer, Rob Eberhardt, + Bill Edney, Kevin Newman, James Crompton, Matthew Mastracci, + Doug Wright, Richard York, Kenneth Kolano, MegaZone, + Thomas Verelst, Mark 'Tarquin' Wilton-Jones, Rainer Åhlfors, + David Zulaica, Ken Kolano, Kevin Newman +*/ + +// ======================================================================= +// TO DO +// ======================================================================= + +// PNG - unclickable content + +// ======================================================================= +// TEST/BUGGY +// ======================================================================= + +// hr{margin:1em auto} (doesn't look right in IE5) + +(function() { + +IE7 = { + toString: function(){return "IE7 version 2.0 (beta3)"} +}; +var appVersion = IE7.appVersion = navigator.appVersion.match(/MSIE (\d\.\d)/)[1]; + +if (/ie7_off/.test(top.location.search) || appVersion < 5) return; + +var Undefined = K(); +var quirksMode = document.compatMode != "CSS1Compat"; +var documentElement = document.documentElement, body, viewport; +var ANON = "!"; +var HEADER = ":link{ie7-link:link}:visited{ie7-link:visited}"; + +// ----------------------------------------------------------------------- +// external +// ----------------------------------------------------------------------- + +var RELATIVE = /^[\w\.]+[^:]*$/; +function makePath(href, path) { + if (RELATIVE.test(href)) href = (path || "") + href; + return href; +}; + +function getPath(href, path) { + href = makePath(href, path); + return href.slice(0, href.lastIndexOf("/") + 1); +}; + +// get the path to this script +var script = document.scripts[document.scripts.length - 1]; +var path = getPath(script.src); + +// we'll use microsoft's http request object to load external files +try { + var httpRequest = new ActiveXObject("Microsoft.XMLHTTP"); +} catch (e) { + // ActiveX disabled +} + +var fileCache = {}; +function loadFile(href, path) { +try { + href = makePath(href, path); + if (!fileCache[href]) { + // easy to load a file huh? + httpRequest.open("GET", href, false); + httpRequest.send(); + if (httpRequest.status == 0 || httpRequest.status == 200) { + fileCache[href] = httpRequest.responseText; + } + } +} catch (e) { + // ignore errors +} finally { + return fileCache[href] || ""; +}}; + +// ----------------------------------------------------------------------- +// IE5.0 compatibility +// ----------------------------------------------------------------------- + + +if (appVersion < 5.5) { + undefined = Undefined(); + + ANON = "HTML:!"; // for anonymous content + + // Fix String.replace (Safari1.x/IE5.0). + var GLOBAL = /(g|gi)$/; + var _String_replace = String.prototype.replace; + String.prototype.replace = function(expression, replacement) { + if (typeof replacement == "function") { // Safari doesn't like functions + if (expression && expression.constructor == RegExp) { + var regexp = expression; + var global = regexp.global; + if (global == null) global = GLOBAL.test(regexp); + // we have to convert global RexpExps for exec() to work consistently + if (global) regexp = new RegExp(regexp.source); // non-global + } else { + regexp = new RegExp(rescape(expression)); + } + var match, string = this, result = ""; + while (string && (match = regexp.exec(string))) { + result += string.slice(0, match.index) + replacement.apply(this, match); + string = string.slice(match.index + match[0].length); + if (!global) break; + } + return result + string; + } + return _String_replace.apply(this, arguments); + }; + + Array.prototype.pop = function() { + if (this.length) { + var i = this[this.length - 1]; + this.length--; + return i; + } + return undefined; + }; + + Array.prototype.push = function() { + for (var i = 0; i < arguments.length; i++) { + this[this.length] = arguments[i]; + } + return this.length; + }; + + var ns = this; + Function.prototype.apply = function(o, a) { + if (o === undefined) o = ns; + else if (o == null) o = window; + else if (typeof o == "string") o = new String(o); + else if (typeof o == "number") o = new Number(o); + else if (typeof o == "boolean") o = new Boolean(o); + if (arguments.length == 1) a = []; + else if (a[0] && a[0].writeln) a[0] = a[0].documentElement.document || a[0]; + var $ = "#ie7_apply", r; + o[$] = this; + switch (a.length) { // unroll for speed + case 0: r = o[$](); break; + case 1: r = o[$](a[0]); break; + case 2: r = o[$](a[0],a[1]); break; + case 3: r = o[$](a[0],a[1],a[2]); break; + case 4: r = o[$](a[0],a[1],a[2],a[3]); break; + case 5: r = o[$](a[0],a[1],a[2],a[3],a[4]); break; + default: + var b = [], i = a.length - 1; + do b[i] = "a[" + i + "]"; while (i--); + eval("r=o[$](" + b + ")"); + } + if (typeof o.valueOf == "function") { // not a COM object + delete o[$]; + } else { + o[$] = undefined; + if (r && r.writeln) r = r.documentElement.document || r; + } + return r; + }; + + Function.prototype.call = function(o) { + return this.apply(o, _slice.apply(arguments, [1])); + }; + + // block elements are "inline" according to IE5.0 so we'll fix it + HEADER += "address,blockquote,body,dd,div,dt,fieldset,form,"+ + "frame,frameset,h1,h2,h3,h4,h5,h6,iframe,noframes,object,p,"+ + "hr,applet,center,dir,menu,pre,dl,li,ol,ul{display:block}"; +} + +// ----------------------------------------------------------------------- +// OO support +// ----------------------------------------------------------------------- + + +// This is a cut-down version of base2 (http://code.google.com/p/base2/) + +var _slice = Array.prototype.slice; + +// private +var _FORMAT = /%([1-9])/g; +var _LTRIM = /^\s\s*/; +var _RTRIM = /\s\s*$/; +var _RESCAPE = /([\/()[\]{}|*+-.,^$?\\])/g; // safe regular expressions +var _BASE = /\bbase\b/; +var _HIDDEN = ["constructor", "toString"]; // only override these when prototyping + +var prototyping; + +function Base(){}; +Base.extend = function(_instance, _static) { + // Build the prototype. + prototyping = true; + var _prototype = new this; + extend(_prototype, _instance); + prototyping = false; + + // Create the wrapper for the constructor function. + var _constructor = _prototype.constructor; + function klass() { + // Don't call the constructor function when prototyping. + if (!prototyping) _constructor.apply(this, arguments); + }; + _prototype.constructor = klass; + + // Build the static interface. + klass.extend = arguments.callee; + extend(klass, _static); + klass.prototype = _prototype; + return klass; +}; +Base.prototype.extend = function(source) { + return extend(this, source); +}; + +// A collection of regular expressions and their associated replacement values. +// A Base class for creating parsers. + +var _HASH = "#"; +var _KEYS = "~"; + +var _RG_ESCAPE_CHARS = /\\./g; +var _RG_ESCAPE_BRACKETS = /\(\?[:=!]|\[[^\]]+\]/g; +var _RG_BRACKETS = /\(/g; + +var RegGrp = Base.extend({ + constructor: function(values) { + this[_KEYS] = []; + this.merge(values); + }, + + exec: function(string) { + var items = this, keys = this[_KEYS]; + return String(string).replace(new RegExp(this, this.ignoreCase ? "gi" : "g"), function() { + var item, offset = 1, i = 0; + // Loop through the RegGrp items. + while ((item = items[_HASH + keys[i++]])) { + var next = offset + item.length + 1; + if (arguments[offset]) { // do we have a result? + var replacement = item.replacement; + switch (typeof replacement) { + case "function": + return replacement.apply(items, _slice.call(arguments, offset, next)); + case "number": + return arguments[offset + replacement]; + default: + return replacement; + } + } + offset = next; + } + }); + }, + + add: function(expression, replacement) { + if (expression instanceof RegExp) { + expression = expression.source; + } + if (!this[_HASH + expression]) this[_KEYS].push(String(expression)); + this[_HASH + expression] = new RegGrp.Item(expression, replacement); + }, + + merge: function(values) { + for (var i in values) this.add(i, values[i]); + }, + + toString: function() { + // back references not supported in simple RegGrp + return "(" + this[_KEYS].join(")|(") + ")"; + } +}, { + IGNORE: "$0", + + Item: Base.extend({ + constructor: function(expression, replacement) { + expression = expression instanceof RegExp ? expression.source : String(expression); + + if (typeof replacement == "number") replacement = String(replacement); + else if (replacement == null) replacement = ""; + + // does the pattern use sub-expressions? + if (typeof replacement == "string" && /\$(\d+)/.test(replacement)) { + // a simple lookup? (e.g. "$2") + if (/^\$\d+$/.test(replacement)) { + // store the index (used for fast retrieval of matched strings) + replacement = parseInt(replacement.slice(1)); + } else { // a complicated lookup (e.g. "Hello $2 $1") + // build a function to do the lookup + var Q = /'/.test(replacement.replace(/\\./g, "")) ? '"' : "'"; + replacement = replacement.replace(/\n/g, "\\n").replace(/\r/g, "\\r").replace(/\$(\d+)/g, Q + + "+(arguments[$1]||" + Q+Q + ")+" + Q); + replacement = new Function("return " + Q + replacement.replace(/(['"])\1\+(.*)\+\1\1$/, "$1") + Q); + } + } + + this.length = RegGrp.count(expression); + this.replacement = replacement; + this.toString = K(expression); + } + }), + + count: function(expression) { + // Count the number of sub-expressions in a RegExp/RegGrp.Item. + expression = String(expression).replace(_RG_ESCAPE_CHARS, "").replace(_RG_ESCAPE_BRACKETS, ""); + return match(expression, _RG_BRACKETS).length; + } +}); + +// ========================================================================= +// lang/extend.js +// ========================================================================= + +function extend(object, source) { // or extend(object, key, value) + if (object && source) { + var proto = (typeof source == "function" ? Function : Object).prototype; + // Add constructor, toString etc + var i = _HIDDEN.length, key; + if (prototyping) while (key = _HIDDEN[--i]) { + var value = source[key]; + if (value != proto[key]) { + if (_BASE.test(value)) { + _override(object, key, value) + } else { + object[key] = value; + } + } + } + // Copy each of the source object's properties to the target object. + for (key in source) if (proto[key] === undefined) { + var value = source[key]; + // Check for method overriding. + if (object[key] && typeof value == "function" && _BASE.test(value)) { + _override(object, key, value); + } else { + object[key] = value; + } + } + } + return object; +}; + +function _override(object, name, method) { + // Override an existing method. + var ancestor = object[name]; + object[name] = function() { + var previous = this.base; + this.base = ancestor; + var returnValue = method.apply(this, arguments); + this.base = previous; + return returnValue; + }; +}; + +function combine(keys, values) { + // Combine two arrays to make a hash. + if (!values) values = keys; + var hash = {}; + for (var i in keys) hash[i] = values[i]; + return hash; +}; + +function format(string) { + // Replace %n with arguments[n]. + // e.g. format("%1 %2%3 %2a %1%3", "she", "se", "lls"); + // ==> "she sells sea shells" + // Only %1 - %9 supported. + var args = arguments; + var _FORMAT = new RegExp("%([1-" + arguments.length + "])", "g"); + return String(string).replace(_FORMAT, function(match, index) { + return index < args.length ? args[index] : match; + }); +}; + +function match(string, expression) { + // Same as String.match() except that this function will return an empty + // array if there is no match. + return String(string).match(expression) || []; +}; + +function rescape(string) { + // Make a string safe for creating a RegExp. + return String(string).replace(_RESCAPE, "\\$1"); +}; + +// http://blog.stevenlevithan.com/archives/faster-trim-javascript +function trim(string) { + return String(string).replace(_LTRIM, "").replace(_RTRIM, ""); +}; + +function K(k) { + return function() { + return k; + }; +}; + +// ----------------------------------------------------------------------- +// parsing +// ----------------------------------------------------------------------- + +var Parser = RegGrp.extend({ignoreCase: true}); + +var ENCODED = /\x01(\d+)/g, + QUOTES = /'/g, + STRING = /^\x01/, + UNICODE = /\\([\da-fA-F]{1,4})/g; + +var _strings = []; + +var encoder = new Parser({ + // comments + "": "", + "\\/\\*[^*]*\\*+([^\\/][^*]*\\*+)*\\/": "", + // get rid + "@(namespace|import)[^;\\n]+[;\\n]": "", + // strings + "'(\\\\.|[^'\\\\])*'": encodeString, + '"(\\\\.|[^"\\\\])*"': encodeString, + // white space + "\\s+": " " +}); + +function encode(cssText) { + return encoder.exec(cssText); +}; + +function decode(cssText) { + return cssText.replace(ENCODED, function(match, index) { + return _strings[index - 1]; + }); +}; + +function encodeString(string) { + return "\x01" + _strings.push(string.replace(UNICODE, function(match, chr) { + return eval("'\\u" + "0000".slice(chr.length) + chr + "'"); + }).slice(1, -1).replace(QUOTES, "\\'")); +}; + +function getString(value) { + return STRING.test(value) ? _strings[value.slice(1) - 1] : value; +}; + +// clone a "width" function to create a "height" function +var rotater = new RegGrp({ + Width: "Height", + width: "height", + Left: "Top", + left: "top", + Right: "Bottom", + right: "bottom", + onX: "onY" +}); + +function rotate(fn) { + return rotater.exec(fn); +}; + +// ----------------------------------------------------------------------- +// event handling +// ----------------------------------------------------------------------- + +var eventHandlers = []; + +function addResize(handler) { + addRecalc(handler); + addEventHandler(window, "onresize", handler); +}; + +// add an event handler (function) to an element +function addEventHandler(element, type, handler) { + element.attachEvent(type, handler); + // store the handler so it can be detached later + eventHandlers.push(arguments); +}; + +// remove an event handler assigned to an element by IE7 +function removeEventHandler(element, type, handler) { +try { + element.detachEvent(type, handler); +} catch (ignore) { + // write a letter of complaint to microsoft.. +}}; + +// remove event handlers (they eat memory) +addEventHandler(window, "onunload", function() { + var handler; + while (handler = eventHandlers.pop()) { + removeEventHandler(handler[0], handler[1], handler[2]); + } +}); + +function register(handler, element, condition) { // -@DRE + //var set = handler[element.uniqueID]; + if (!handler.elements) handler.elements = {}; + if (condition) handler.elements[element.uniqueID] = element; + else delete handler.elements[element.uniqueID]; + //return !set && condition; + return condition; +}; + +addEventHandler(window, "onbeforeprint", function() { + if (!IE7.CSS.print) new StyleSheet("print"); + IE7.CSS.print.recalc(); +}); + +// ----------------------------------------------------------------------- +// pixel conversion +// ----------------------------------------------------------------------- + +// this is handy because it means that web developers can mix and match +// measurement units in their style sheets. it is not uncommon to +// express something like padding in "em" units whilst border thickness +// is most often expressed in pixels. + +var PIXEL = /^\d+(px)?$/i; +var PERCENT = /^\d+%$/; +var getPixelValue = function(element, value) { + if (PIXEL.test(value)) return parseInt(value); + var style = element.style.left; + var runtimeStyle = element.runtimeStyle.left; + element.runtimeStyle.left = element.currentStyle.left; + element.style.left = value || 0; + value = element.style.pixelLeft; + element.style.left = style; + element.runtimeStyle.left = runtimeStyle; + return value; +}; + +// ----------------------------------------------------------------------- +// generic +// ----------------------------------------------------------------------- + +var $IE7 = "ie7-"; + +var Fix = Base.extend({ + constructor: function() { + this.fixes = []; + this.recalcs = []; + }, + init: Undefined +}); + +// a store for functions that will be called when refreshing IE7 +var recalcs = []; +function addRecalc(recalc) { + recalcs.push(recalc); +}; + +IE7.recalc = function() { + IE7.HTML.recalc(); + // re-apply style sheet rules (re-calculate ie7 classes) + IE7.CSS.recalc(); + // apply global fixes to the document + for (var i = 0; i < recalcs.length; i++) recalcs[i](); +}; + +function isFixed(element) { + return element.currentStyle["ie7-position"] == "fixed"; +}; + +// original style +function getDefinedStyle(element, propertyName) { + return element.currentStyle[$IE7 + propertyName] || element.currentStyle[propertyName]; +}; + +function setOverrideStyle(element, propertyName, value) { + if (element.currentStyle[$IE7 + propertyName] == null) { + element.runtimeStyle[$IE7 + propertyName] = element.currentStyle[propertyName]; + } + element.runtimeStyle[propertyName] = value; +}; + +// create a temporary element which is used to inherit styles +// from the target element. the temporary element can be resized +// to determine pixel widths/heights +function createTempElement(tagName) { + var element = document.createElement(tagName || "object"); + element.style.cssText = "position:absolute;padding:0;display:block;border:none;clip:rect(0 0 0 0);left:-9999"; + element.ie7_anon = true; + return element; +}; + + +// ========================================================================= +// ie7-cssQuery.js +// ========================================================================= + +function cssQuery(selector, context, single) { + if (!_cache[selector]) { + reg = []; // store for RegExp objects + var fn = ""; + var selectors = cssParser.escape(selector).split(","); + for (var i = 0; i < selectors.length; i++) { + _wild = _index = _list = 0; // reset + _duplicate = selectors.length > 1 ? 2 : 0; // reset + var block = cssParser.exec(selectors[i]) || "if(0){"; + if (_wild) { // IE's pesky comment nodes + block += format("if(e%1.nodeName!='!'){", _index); + } + // check for duplicates before storing results + var store = _duplicate > 1 ? _TEST : ""; + block += format(store + _STORE, _index); + // add closing braces + block += Array(match(block, /\{/g).length + 1).join("}"); + fn += block; + } + eval(format(_FN, reg) + cssParser.unescape(fn) + "return s?null:r}"); + _cache[selector] = _selectorFunction; + } + return _cache[selector](context || document, single); +}; + +var _MSIE5 = appVersion < 6; + +var _EVALUATED = /^(href|src)$/; +var _ATTRIBUTES = { + "class": "className", + "for": "htmlFor" +}; + +IE7._indexed = 1; + +IE7._byId = function(document, id) { + var result = document.all[id] || null; + // returns a single element or a collection + if (!result || result.id == id) return result; + // document.all has returned a collection of elements with name/id + for (var i = 0; i < result.length; i++) { + if (result[i].id == id) return result[i]; + } + return null; +}; + +IE7._getAttribute = function(element, name) { + if (name == "src" && element.pngSrc) return element.pngSrc; + + var attribute = _MSIE5 ? (element.attributes[name] || element.attributes[_ATTRIBUTES[name.toLowerCase()]]) : element.getAttributeNode(name); + if (attribute && (attribute.specified || name == "value")) { + if (_EVALUATED.test(name)) { + return element.getAttribute(name, 2); + } else if (name == "class") { + return element.className.replace(/\sie7_\w+/g, ""); + } else if (name == "style") { + return element.style.cssText; + } else { + return attribute.nodeValue; + } + } + return null; +}; + +var names = "colSpan,rowSpan,vAlign,dateTime,accessKey,tabIndex,encType,maxLength,readOnly,longDesc"; +// Convert the list of strings to a hash, mapping the lowercase name to the camelCase name. +extend(_ATTRIBUTES, combine(names.toLowerCase().split(","), names.split(","))); + +IE7._getNextElementSibling = function(node) { + // return the next element to the supplied element + // nextSibling is not good enough as it might return a text or comment node + while (node && (node = node.nextSibling) && (node.nodeType != 1 || node.nodeName == "!")) continue; + return node; +}; + +IE7._getPreviousElementSibling = function(node) { + // return the previous element to the supplied element + while (node && (node = node.previousSibling) && (node.nodeType != 1 || node.nodeName == "!")) continue; + return node; +}; + +// ========================================================================= +// CSSParser +// ========================================================================= + +var IMPLIED_ASTERISK = /([\s>+~,]|[^(]\+|^)([#.:\[])/g, + IMPLIED_SPACE = /(^|,)([^\s>+~])/g, + WHITESPACE = /\s*([\s>+~(),]|^|$)\s*/g, + WILD_CARD = /\s\*\s/g;; + +var CSSParser = RegGrp.extend({ + constructor: function(items) { + this.base(items); + this.sorter = new RegGrp; + this.sorter.add(/:not\([^)]*\)/, RegGrp.IGNORE); + this.sorter.add(/([ >](\*|[\w-]+))([^: >+~]*)(:\w+-child(\([^)]+\))?)([^: >+~]*)/, "$1$3$6$4"); + }, + + ignoreCase: true, + + escape: function(selector) { + return this.optimise(this.format(selector)); + }, + + format: function(selector) { + return selector + .replace(WHITESPACE, "$1") + .replace(IMPLIED_SPACE, "$1 $2") + .replace(IMPLIED_ASTERISK, "$1*$2"); + }, + + optimise: function(selector) { + // optimise wild card descendant selectors + return this.sorter.exec(selector.replace(WILD_CARD, ">* ")); + }, + + unescape: function(selector) { + return decode(selector); + } +}); + +// some constants +var _OPERATORS = { + "": "%1!=null", + "=": "%1=='%2'", + "~=": /(^| )%1( |$)/, + "|=": /^%1(-|$)/, + "^=": /^%1/, + "$=": /%1$/, + "*=": /%1/ +}; + +var _PSEUDO_CLASSES = { + "first-child": "!IE7._getPreviousElementSibling(e%1)", + "link": "e%1.currentStyle['ie7-link']=='link'", + "visited": "e%1.currentStyle['ie7-link']=='visited'" +}; + +var _VAR = "var p%2=0,i%2,e%2,n%2=e%1."; +var _ID = "e%1.sourceIndex"; +var _TEST = "var g=" + _ID + ";if(!p[g]){p[g]=1;"; +var _STORE = "r[r.length]=e%1;if(s)return e%1;"; +var _FN = "var _selectorFunction=function(e0,s){IE7._indexed++;var r=[],p={},reg=[%1],d=document;"; +var reg; // a store for RexExp objects +var _index; +var _wild; // need to flag certain _wild card selectors as MSIE includes comment nodes +var _list; // are we processing a node _list? +var _duplicate; // possible duplicates? +var _cache = {}; // store parsed selectors + +// a hideous parser +var cssParser = new CSSParser({ + " (\\*|[\\w-]+)#([\\w-]+)": function(match, tagName, id) { // descendant selector followed by ID + _wild = false; + var replacement = "var e%2=IE7._byId(d,'%4');if(e%2&&"; + if (tagName != "*") replacement += "e%2.nodeName=='%3'&&"; + replacement += "(e%1==d||e%1.contains(e%2))){"; + if (_list) replacement += format("i%1=n%1.length;", _list); + return format(replacement, _index++, _index, tagName.toUpperCase(), id); + }, + + " (\\*|[\\w-]+)": function(match, tagName) { // descendant selector + _duplicate++; // this selector may produce duplicates + _wild = tagName == "*"; + var replacement = _VAR; + // IE5.x does not support getElementsByTagName("*"); + replacement += (_wild && _MSIE5) ? "all" : "getElementsByTagName('%3')"; + replacement += ";for(i%2=0;(e%2=n%2[i%2]);i%2++){"; + return format(replacement, _index++, _list = _index, tagName.toUpperCase()); + }, + + ">(\\*|[\\w-]+)": function(match, tagName) { // child selector + var children = _list; + _wild = tagName == "*"; + var replacement = _VAR; + // use the children property for MSIE as it does not contain text nodes + // (but the children collection still includes comments). + // the document object does not have a children collection + replacement += children ? "children": "childNodes"; + if (!_wild && children) replacement += ".tags('%3')"; + replacement += ";for(i%2=0;(e%2=n%2[i%2]);i%2++){"; + if (_wild) { + replacement += "if(e%2.nodeType==1){"; + _wild = _MSIE5; + } else { + if (!children) replacement += "if(e%2.nodeName=='%3'){"; + } + return format(replacement, _index++, _list = _index, tagName.toUpperCase()); + }, + + "\\+(\\*|[\\w-]+)": function(match, tagName) { // direct adjacent selector + var replacement = ""; + if (_wild) replacement += "if(e%1.nodeName!='!'){"; + _wild = false; + replacement += "e%1=IE7._getNextElementSibling(e%1);if(e%1"; + if (tagName != "*") replacement += "&&e%1.nodeName=='%2'"; + replacement += "){"; + return format(replacement, _index, tagName.toUpperCase()); + }, + + "~(\\*|[\\w-]+)": function(match, tagName) { // indirect adjacent selector + var replacement = ""; + if (_wild) replacement += "if(e%1.nodeName!='!'){"; + _wild = false; + _duplicate = 2; // this selector may produce duplicates + replacement += "while(e%1=e%1.nextSibling){if(e%1.ie7_adjacent==IE7._indexed)break;if("; + if (tagName == "*") { + replacement += "e%1.nodeType==1"; + if (_MSIE5) replacement += "&&e%1.nodeName!='!'"; + } else replacement += "e%1.nodeName=='%2'"; + replacement += "){e%1.ie7_adjacent=IE7._indexed;"; + return format(replacement, _index, tagName.toUpperCase()); + }, + + "#([\\w-]+)": function(match, id) { // ID selector + _wild = false; + var replacement = "if(e%1.id=='%2'){"; + if (_list) replacement += format("i%1=n%1.length;", _list); + return format(replacement, _index, id); + }, + + "\\.([\\w-]+)": function(match, className) { // class selector + _wild = false; + // store RegExp objects - slightly faster on IE + reg.push(new RegExp("(^|\\s)" + rescape(className) + "(\\s|$)")); + return format("if(e%1.className&®[%2].test(e%1.className)){", _index, reg.length - 1); + }, + + "\\[([\\w-]+)\\s*([^=]?=)?\\s*([^\\]]*)\\]": function(match, attr, operator, value) { // attribute selectors + var alias = _ATTRIBUTES[attr] || attr; + if (operator) { + var getAttribute = "e%1.getAttribute('%2',2)"; + if (!_EVALUATED.test(attr)) { + getAttribute = "e%1.%3||" + getAttribute; + } + attr = format("(" + getAttribute + ")", _index, attr, alias); + } else { + attr = format("IE7._getAttribute(e%1,'%2')", _index, attr); + } + var replacement = _OPERATORS[operator || ""] || "0"; + if (replacement && replacement.source) { + reg.push(new RegExp(format(replacement.source, rescape(cssParser.unescape(value))))); + replacement = "reg[%2].test(%1)"; + value = reg.length - 1; + } + return "if(" + format(replacement, attr, value) + "){"; + }, + + ":+([\\w-]+)(\\(([^)]+)\\))?": function(match, pseudoClass, $2, args) { // pseudo class selectors + pseudoClass = _PSEUDO_CLASSES[pseudoClass]; + return "if(" + (pseudoClass ? format(pseudoClass, _index, args || "") : "0") + "){"; + } +}); + +// ========================================================================= +// ie7-css.js +// ========================================================================= + +var HYPERLINK = /a(#[\w-]+)?(\.[\w-]+)?:(hover|active)/i; +var BRACE1 = /\s*\{\s*/, BRACE2 = /\s*\}\s*/, COMMA = /\s*\,\s*/; +var FIRST_LINE_LETTER = /(.*)(:first-(line|letter))/; + +//var UNKNOWN = /UNKNOWN|([:.])\w+\1/i; + +var styleSheets = document.styleSheets; + +IE7.CSS = new (Fix.extend({ // single instance + parser: new Parser, + screen: "", + print: "", + styles: [], + rules: [], + pseudoClasses: appVersion < 7 ? "first\\-child" : "", + dynamicPseudoClasses: { + toString: function() { + var strings = []; + for (var pseudoClass in this) strings.push(pseudoClass); + return strings.join("|"); + } + }, + + init: function() { + var NONE = "^\x01$"; + var CLASS = "\\[class=?[^\\]]*\\]"; + var pseudoClasses = []; + if (this.pseudoClasses) pseudoClasses.push(this.pseudoClasses); + var dynamicPseudoClasses = this.dynamicPseudoClasses.toString(); + if (dynamicPseudoClasses) pseudoClasses.push(dynamicPseudoClasses); + pseudoClasses = pseudoClasses.join("|"); + var unknown = appVersion < 7 ? ["[>+~[(]|([:.])\\w+\\1"] : [CLASS]; + if (pseudoClasses) unknown.push(":(" + pseudoClasses + ")"); + this.UNKNOWN = new RegExp(unknown.join("|") || NONE, "i"); + var complex = appVersion < 7 ? ["\\[[^\\]]+\\]|[^\\s(\\[]+\\s*[+~]"] : [CLASS]; + var complexRule = complex.concat(); + if (pseudoClasses) complexRule.push(":(" + pseudoClasses + ")"); + Rule.COMPLEX = new RegExp(complexRule.join("|") || NONE, "ig"); + if (this.pseudoClasses) complex.push(":(" + this.pseudoClasses + ")"); + DynamicRule.COMPLEX = new RegExp(complex.join("|") || NONE, "i"); + DynamicRule.MATCH = new RegExp(dynamicPseudoClasses ? "(.*):(" + dynamicPseudoClasses + ")(.*)" : NONE, "i"); + + this.createStyleSheet(); + this.refresh(); + }, + + addEventHandler: function() { + addEventHandler.apply(null, arguments); + }, + + addFix: function(expression, replacement) { + this.parser.add(expression, replacement); + }, + + addRecalc: function(propertyName, test, handler, replacement) { + // recalcs occur whenever the document is refreshed using document.recalc() + test = new RegExp("([{;\\s])" + propertyName + "\\s*:\\s*" + test + "[^;}]*"); + var id = this.recalcs.length; + if (replacement) replacement = propertyName + ":" + replacement; + this.addFix(test, function(match, $1) { + return (replacement ? $1 + replacement : match) + ";ie7-" + match.slice(1) + ";ie7_recalc" + id + ":1"; + }); + this.recalcs.push(arguments); + return id; + }, + + apply: function() { + this.getInlineStyles(); + new StyleSheet("screen"); + this.trash(); + }, + + createStyleSheet: function() { + // create the IE7 style sheet + this.styleSheet = document.createStyleSheet(); + // flag it so we can ignore it during parsing + this.styleSheet.ie7 = true; + this.styleSheet.owningElement.ie7 = true; + this.styleSheet.cssText = HEADER; + }, + + getInlineStyles: function() { + // load inline styles + var styleSheets = document.getElementsByTagName("style"), styleSheet; + for (var i = styleSheets.length - 1; (styleSheet = styleSheets[i]); i--) { + if (!styleSheet.disabled && !styleSheet.ie7) { + this.styles.push(styleSheet.innerHTML); + } + } + }, + + getText: function(styleSheet, path) { + // explorer will trash unknown selectors (it converts them to "UNKNOWN"). + // so we must reload external style sheets (internal style sheets can have their text + // extracted through the innerHTML property). + // load the style sheet text from an external file + try { + var cssText = styleSheet.cssText; + } catch (e) { + cssText = ""; + } + if (httpRequest) cssText = loadFile(styleSheet.href, path) || cssText; + return cssText; + }, + + recalc: function() { + this.screen.recalc(); + // we're going to read through all style rules. + // certain rules have had ie7 properties added to them. + // e.g. p{top:0; ie7_recalc2:1; left:0} + // this flags a property in the rule as needing a fix. + // the selector text is then used to query the document. + // we can then loop through the results of the query + // and fix the elements. + // we ignore the IE7 rules - so count them in the header + var RECALCS = /ie7_recalc\d+/g; + var start = HEADER.match(/[{,]/g).length; + // only calculate screen fixes. print fixes don't show up anyway + var stop = start + (this.screen.cssText.match(/\{/g)||"").length; + var rules = this.styleSheet.rules, rule; + var calcs, calc, elements, element, i, j, k, id; + // loop through all rules + for (i = start; i < stop; i++) { + rule = rules[i]; + var cssText = rule.style.cssText; + // search for the "ie7_recalc" flag (there may be more than one) + if (rule && (calcs = cssText.match(RECALCS))) { + // use the selector text to query the document + elements = cssQuery(rule.selectorText); + // if there are matching elements then loop + // through the recalc functions and apply them + // to each element + if (elements.length) for (j = 0; j < calcs.length; j++) { + // get the matching flag (e.g. ie7_recalc3) + id = calcs[j]; + // extract the numeric id from the end of the flag + // and use it to index the collection of recalc + // functions + calc = IE7.CSS.recalcs[id.slice(10)][2]; + for (k = 0; (element = elements[k]); k++) { + // apply the fix + if (element.currentStyle[id]) calc(element, cssText); + } + } + } + } + }, + + refresh: function() { + this.styleSheet.cssText = HEADER + this.screen + this.print; + }, + + trash: function() { + // trash the old style sheets + for (var i = 0; i < styleSheets.length; i++) { + if (!styleSheets[i].ie7) { + try { + var cssText = styleSheets[i].cssText; + } catch (e) { + cssText = ""; + } + if (cssText) styleSheets[i].cssText = ""; + } + } + } +})); + +// ----------------------------------------------------------------------- +// IE7 StyleSheet class +// ----------------------------------------------------------------------- + +var StyleSheet = Base.extend({ + constructor: function(media) { + this.media = media; + this.load(); + IE7.CSS[media] = this; + IE7.CSS.refresh(); + }, + + createRule: function(selector, cssText) { + if (IE7.CSS.UNKNOWN.test(selector)) { + var match; + if (PseudoElement && (match = selector.match(PseudoElement.MATCH))) { + return new PseudoElement(match[1], match[2], cssText); + } else if (match = selector.match(DynamicRule.MATCH)) { + if (!HYPERLINK.test(match[0]) || DynamicRule.COMPLEX.test(match[0])) { + return new DynamicRule(selector, match[1], match[2], match[3], cssText); + } + } else return new Rule(selector, cssText); + } + return selector + " {" + cssText + "}"; + }, + + getText: function() { + // store for style sheet text + var _inlineStyles = [].concat(IE7.CSS.styles); + // parse media decalarations + var MEDIA = /@media\s+([^{]*)\{([^@]+\})\s*\}/gi; + var ALL = /\ball\b|^$/i, SCREEN = /\bscreen\b/i, PRINT = /\bprint\b/i; + function _parseMedia(cssText, media) { + _filterMedia.value = media; + return cssText.replace(MEDIA, _filterMedia); + }; + function _filterMedia(match, media, cssText) { + media = _simpleMedia(media); + switch (media) { + case "screen": + case "print": + if (media != _filterMedia.value) return ""; + case "all": + return cssText; + } + return ""; + }; + function _simpleMedia(media) { + if (ALL.test(media)) return "all"; + else if (SCREEN.test(media)) return (PRINT.test(media)) ? "all" : "screen"; + else if (PRINT.test(media)) return "print"; + }; + var self = this; + function _getCSSText(styleSheet, path, media, level) { + var cssText = ""; + if (!level) { + media = _simpleMedia(styleSheet.media); + level = 0; + } + if (media == "all" || media == self.media) { + // IE only allows importing style sheets three levels deep. + // it will crash if you try to access a level below this + if (level < 3) { + // loop through imported style sheets + for (var i = 0; i < styleSheet.imports.length; i++) { + // call this function recursively to get all imported style sheets + cssText += _getCSSText(styleSheet.imports[i], getPath(styleSheet.href, path), media, level + 1); + } + } + // retrieve inline style or load an external style sheet + cssText += encode(styleSheet.href ? _loadStyleSheet(styleSheet, path) : _inlineStyles.pop() || ""); + cssText = _parseMedia(cssText, self.media); + } + return cssText; + }; + // store loaded cssText URLs + var fileCache = {}; + // load an external style sheet + function _loadStyleSheet(styleSheet, path) { + var url = makePath(styleSheet.href, path); + // if the style sheet has already loaded then don't duplicate it + if (fileCache[url]) return ""; + // load from source + fileCache[url] = (styleSheet.disabled) ? "" : + _fixUrls(IE7.CSS.getText(styleSheet, path), getPath(styleSheet.href, path)); + return fileCache[url]; + }; + // fix css paths + // we're lumping all css text into one big style sheet so relative + // paths have to be fixed. this is necessary anyway because of other + // explorer bugs. + var URL = /(url\s*\(\s*['"]?)([\w\.]+[^:\)]*['"]?\))/gi; + function _fixUrls(cssText, pathname) { + // hack & slash + return cssText.replace(URL, "$1" + pathname.slice(0, pathname.lastIndexOf("/") + 1) + "$2"); + }; + + // load all style sheets in the document + for (var i = 0; i < styleSheets.length; i++) { + if (!styleSheets[i].disabled && !styleSheets[i].ie7) { + this.cssText += _getCSSText(styleSheets[i]); + } + } + }, + + load: function() { + this.cssText = ""; + this.getText(); + this.parse(); + this.cssText = decode(this.cssText); + fileCache = {}; + }, + + parse: function() { + this.cssText = IE7.CSS.parser.exec(this.cssText); + + // parse the style sheet + var offset = IE7.CSS.rules.length; + var rules = this.cssText.split(BRACE2), rule; + var selectors, cssText, i, j; + for (i = 0; i < rules.length; i++) { + rule = rules[i].split(BRACE1); + selectors = rule[0].split(COMMA); + cssText = rule[1]; + for (j = 0; j < selectors.length; j++) { + selectors[j] = cssText ? this.createRule(selectors[j], cssText) : ""; + } + rules[i] = selectors.join("\n"); + } + this.cssText = rules.join("\n"); + this.rules = IE7.CSS.rules.slice(offset); + }, + + recalc: function() { + var rule, i; + for (i = 0; (rule = this.rules[i]); i++) rule.recalc(); + }, + + toString: function() { + return "@media " + this.media + "{" + this.cssText + "}"; + } +}); + +var PseudoElement; + +// ----------------------------------------------------------------------- +// IE7 style rules +// ----------------------------------------------------------------------- + +var Rule = IE7.Rule = Base.extend({ + // properties + constructor: function(selector, cssText) { + this.id = IE7.CSS.rules.length; + this.className = Rule.PREFIX + this.id; + selector = selector.match(FIRST_LINE_LETTER) || selector || "*"; + this.selector = selector[1] || selector; + this.selectorText = this.parse(this.selector) + (selector[2] || ""); + this.cssText = cssText; + this.MATCH = new RegExp("\\s" + this.className + "(\\s|$)", "g"); + IE7.CSS.rules.push(this); + this.init(); + }, + + init: Undefined, + + add: function(element) { + // allocate this class + element.className += " " + this.className; + }, + + recalc: function() { + // execute the underlying css query for this class + var match = cssQuery(this.selector); + // add the class name for all matching elements + for (var i = 0; i < match.length; i++) this.add(match[i]); + }, + + parse: function(selector) { + // attempt to preserve specificity for "loose" parsing by + // removing unknown tokens from a css selector but keep as + // much as we can.. + var simple = selector.replace(Rule.CHILD, " ").replace(Rule.COMPLEX, ""); + if (appVersion < 7) simple = simple.replace(Rule.MULTI, ""); + var tags = match(simple, Rule.TAGS).length - match(selector, Rule.TAGS).length; + var classes = match(simple, Rule.CLASSES).length - match(selector, Rule.CLASSES).length + 1; + while (classes > 0 && Rule.CLASS.test(simple)) { + simple = simple.replace(Rule.CLASS, ""); + classes--; + } + while (tags > 0 && Rule.TAG.test(simple)) { + simple = simple.replace(Rule.TAG, "$1*"); + tags--; + } + simple += "." + this.className; + classes = Math.min(classes, 2); + tags = Math.min(tags, 2); + var score = -10 * classes - tags; + if (score > 0) { + simple = simple + "," + Rule.MAP[score] + " " + simple; + } + return simple; + }, + + remove: function(element) { + // deallocate this class + element.className = element.className.replace(this.MATCH, "$1"); + }, + + toString: function() { + return format("%1 {%2}", this.selectorText, this.cssText); + } +}, { + CHILD: />/g, + CLASS: /\.[\w-]+/, + CLASSES: /[.:\[]/g, + MULTI: /(\.[\w-]+)+/g, + PREFIX: "ie7_class", + TAG: /^\w+|([\s>+~])\w+/, + TAGS: /^\w|[\s>+~]\w/g, + MAP: { + 1: "html", + 2: "html body", + 10: ".ie7_html", + 11: "html.ie7_html", + 12: "html.ie7_html body", + 20: ".ie7_html .ie7_body", + 21: "html.ie7_html .ie7_body", + 22: "html.ie7_html body.ie7_body" + } +}); + +// ----------------------------------------------------------------------- +// IE7 dynamic style +// ----------------------------------------------------------------------- + +// object properties: +// attach: the element that an event handler will be attached to +// target: the element that will have the IE7 class applied + +var DynamicRule = Rule.extend({ + // properties + constructor: function(selector, attach, dynamicPseudoClass, target, cssText) { + // initialise object properties + this.attach = attach || "*"; + this.dynamicPseudoClass = IE7.CSS.dynamicPseudoClasses[dynamicPseudoClass]; + this.target = target; + this.base(selector, cssText); + }, + + recalc: function() { + // execute the underlying css query for this class + var attaches = cssQuery(this.attach), attach; + // process results + for (var i = 0; attach = attaches[i]; i++) { + // retrieve the event handler's target element(s) + var target = this.target ? cssQuery(this.target, attach) : [attach]; + // attach event handlers for dynamic pseudo-classes + if (target.length) this.dynamicPseudoClass.apply(attach, target, this); + } + } +}); + +// ----------------------------------------------------------------------- +// IE7 dynamic pseudo-classes +// ----------------------------------------------------------------------- + +var DynamicPseudoClass = Base.extend({ + constructor: function(name, apply) { + this.name = name; + this.apply = apply; + this.instances = {}; + IE7.CSS.dynamicPseudoClasses[name] = this; + }, + + register: function(instance) { + // an "instance" is actually an Arguments object + var _class = instance[2]; + instance.id = _class.id + instance[0].uniqueID; + if (!this.instances[instance.id]) { + var target = instance[1], j; + for (j = 0; j < target.length; j++) _class.add(target[j]); + this.instances[instance.id] = instance; + } + }, + + unregister: function(instance) { + if (this.instances[instance.id]) { + var _class = instance[2]; + var target = instance[1], j; + for (j = 0; j < target.length; j++) _class.remove(target[j]); + delete this.instances[instance.id]; + } + } +}); + +// ----------------------------------------------------------------------- +// dynamic pseudo-classes +// ----------------------------------------------------------------------- + +if (appVersion < 7) { + var Hover = new DynamicPseudoClass("hover", function(element) { + var instance = arguments; + IE7.CSS.addEventHandler(element, appVersion < 5.5 ? "onmouseover" : "onmouseenter", function() { + Hover.register(instance); + }); + IE7.CSS.addEventHandler(element, appVersion < 5.5 ? "onmouseout" : "onmouseleave", function() { + Hover.unregister(instance); + }); + }); + + // globally trap the mouseup event (thanks Martijn!) + addEventHandler(document, "onmouseup", function() { + var instances = Hover.instances; + for (var i in instances) + if (!instances[i][0].contains(event.srcElement)) + Hover.unregister(instances[i]); + }); +} + +// ----------------------------------------------------------------------- +// propertyName: inherit; +// ----------------------------------------------------------------------- + +IE7.CSS.addRecalc("[\\w-]+", "inherit", function(element, cssText) { + var inherited = cssText.match(/[\w-]+\s*:\s*inherit/g); + for (var i = 0; i < inherited.length; i++) { + var propertyName = inherited[i].replace(/ie7\-|\s*:\s*inherit/g, "").replace(/\-([a-z])/g, function(match, chr) { + return chr.toUpperCase() + }); + element.runtimeStyle[propertyName] = element.parentElement.currentStyle[propertyName]; + } +}); + +// ========================================================================= +// ie7-html.js +// ========================================================================= + +// default font-sizes +//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}"; + +IE7.HTML = new (Fix.extend({ // single instance + fixed: {}, + + init: Undefined, + + addFix: function() { + // fixes are a one-off, they are applied when the document is loaded + this.fixes.push(arguments); + }, + + apply: function() { + for (var i = 0; i < this.fixes.length; i++) { + var match = cssQuery(this.fixes[i][0]); + var fix = this.fixes[i][1]; + for (var j = 0; j < match.length; j++) fix(match[j]); + } + }, + + addRecalc: function() { + // recalcs occur whenever the document is refreshed using document.recalc() + this.recalcs.push(arguments); + }, + + recalc: function() { + // loop through the fixes + for (var i = 0; i < this.recalcs.length; i++) { + var match = cssQuery(this.recalcs[i][0]); + var recalc = this.recalcs[i][1], element; + var key = Math.pow(2, i); + for (var j = 0; (element = match[j]); j++) { + var uniqueID = element.uniqueID; + if ((this.fixed[uniqueID] & key) == 0) { + element = recalc(element) || element; + this.fixed[uniqueID] |= key; + } + } + } + } +})); + +if (appVersion < 7) { + // provide support for the tag. + // this is a proper fix, it preserves the DOM structure and + // elements report the correct tagName & namespace prefix + document.createElement("abbr"); + + // bind to the first child control + IE7.HTML.addRecalc("label", function(label) { + if (!label.htmlFor) { + var firstChildControl = cssQuery("input,textarea", label, true); + if (firstChildControl) { + addEventHandler(label, "onclick", function() { + firstChildControl.click(); + }); + } + } + }); +} + +// ========================================================================= +// ie7-layout.js +// ========================================================================= + +var NUMERIC = "[.\\d]"; + +new function(_) { +var layout = IE7.Layout = this; + + // big, ugly box-model hack + min/max stuff + + // #tantek > #erik > #dean { voice-family: hacker; } + + // ----------------------------------------------------------------------- + // "layout" + // ----------------------------------------------------------------------- + + HEADER += "*{boxSizing:content-box}"; + + // does an element have "layout" ? + IE7.hasLayout = appVersion < 5.5 ? function(element) { + // element.currentStyle.hasLayout doesn't work for IE5.0 + return element.clientWidth; + } : function(element) { + return element.currentStyle.hasLayout; + }; + + // give an element "layout" + layout.boxSizing = function(element) { + if (!IE7.hasLayout(element)) { + //# element.runtimeStyle.fixedHeight = + element.style.height = "0cm"; + if (element.currentStyle.verticalAlign == "auto") + element.runtimeStyle.verticalAlign = "top"; + // when an element acquires "layout", margins no longer collapse correctly + collapseMargins(element); + } + }; + + // ----------------------------------------------------------------------- + // Margin Collapse + // ----------------------------------------------------------------------- + + function collapseMargins(element) { + if (element != viewport && element.currentStyle.position != "absolute") { + collapseMargin(element, "marginTop"); + collapseMargin(element, "marginBottom"); + } + }; + + function collapseMargin(element, type) { + if (!element.runtimeStyle[type]) { + var parentElement = element.parentElement; + if (parentElement && IE7.hasLayout(parentElement) && !IE7[type == "marginTop" ? "_getPreviousElementSibling" : "_getNextElementSibling"](element)) return; + var child = cssQuery(">*:" + (type == "marginTop" ? "first" : "last") + "-child", element, true); + if (child && child.currentStyle.styleFloat == "none" && IE7.hasLayout(child)) { + collapseMargin(child, type); + margin = _getMargin(element, element.currentStyle[type]); + childMargin = _getMargin(child, child.currentStyle[type]); + if (margin < 0 || childMargin < 0) { + element.runtimeStyle[type] = margin + childMargin; + } else { + element.runtimeStyle[type] = Math.max(childMargin, margin); + } + child.runtimeStyle[type] = "0px"; + } + } + }; + + function _getMargin(element, value) { + return value == "auto" ? 0 : getPixelValue(element, value); + }; + + // ----------------------------------------------------------------------- + // box-model + // ----------------------------------------------------------------------- + + // constants + var UNIT = /^[.\d][\w%]*$/, AUTO = /^(auto|0cm)$/; + + var applyWidth, applyHeight; + IE7.Layout.borderBox = function(element){ + applyWidth(element); + applyHeight(element); + }; + + var fixWidth = function(HEIGHT) { + applyWidth = function(element) { + if (!PERCENT.test(element.currentStyle.width)) fixWidth(element); + collapseMargins(element); + }; + + function fixWidth(element, value) { + if (!element.runtimeStyle.fixedWidth) { + if (!value) value = element.currentStyle.width; + element.runtimeStyle.fixedWidth = (UNIT.test(value)) ? Math.max(0, getFixedWidth(element, value)) : value; + setOverrideStyle(element, "width", element.runtimeStyle.fixedWidth); + } + }; + + function layoutWidth(element) { + if (!isFixed(element)) { + var layoutParent = element.offsetParent; + while (layoutParent && !IE7.hasLayout(layoutParent)) layoutParent = layoutParent.offsetParent; + } + return (layoutParent || viewport).clientWidth; + }; + + function getPixelWidth(element, value) { + if (PERCENT.test(value)) return parseInt(parseFloat(value) / 100 * layoutWidth(element)); + return getPixelValue(element, value); + }; + + var getFixedWidth = function(element, value) { + var borderBox = element.currentStyle["box-sizing"] == "border-box"; + var adjustment = 0; + if (quirksMode && !borderBox) + adjustment += getBorderWidth(element) + getWidth(element, "padding"); + else if (!quirksMode && borderBox) + adjustment -= getBorderWidth(element) + getWidth(element, "padding"); + return getPixelWidth(element, value) + adjustment; + }; + + // easy way to get border thickness for elements with "layout" + function getBorderWidth(element) { + return element.offsetWidth - element.clientWidth; + }; + + // have to do some pixel conversion to get padding/margin thickness :-( + function getWidth(element, type) { + return getPixelWidth(element, element.currentStyle[type + "Left"]) + getPixelWidth(element, element.currentStyle[type + "Right"]); + }; + + // ----------------------------------------------------------------------- + // min/max + // ----------------------------------------------------------------------- + + HEADER += "*{minWidth:none;maxWidth:none;min-width:none;max-width:none}"; + + // handle min-width property + layout.minWidth = function(element) { + // IE6 supports min-height so we frig it here + //#if (element.currentStyle.minHeight == "auto") element.runtimeStyle.minHeight = 0; + if (element.currentStyle["min-width"] != null) { + element.style.minWidth = element.currentStyle["min-width"]; + } + if (register(arguments.callee, element, element.currentStyle.minWidth != "none")) { + layout.boxSizing(element); + fixWidth(element); + resizeWidth(element); + } + }; + + // clone the minWidth function to make a maxWidth function + eval("IE7.Layout.maxWidth=" + String(layout.minWidth).replace(/min/g, "max")); + + // apply min/max restrictions + function resizeWidth(element) { + // check boundaries + var rect = element.getBoundingClientRect(); + var width = rect.right - rect.left; + + if (element.currentStyle.minWidth != "none" && width <= getFixedWidth(element, element.currentStyle.minWidth)) { + element.runtimeStyle.width = element.currentStyle.minWidth; + } else if (element.currentStyle.maxWidth != "none" && width >= getFixedWidth(element, element.currentStyle.maxWidth)) { + element.runtimeStyle.width = element.currentStyle.maxWidth; + } else { + element.runtimeStyle.width = element.runtimeStyle.fixedWidth; // || "auto"; + } + }; + + // ----------------------------------------------------------------------- + // right/bottom + // ----------------------------------------------------------------------- + + function fixRight(element) { + if (register(fixRight, element, /^(fixed|absolute)$/.test(element.currentStyle.position) && + getDefinedStyle(element, "left") != "auto" && + getDefinedStyle(element, "right") != "auto" && + AUTO.test(getDefinedStyle(element, "width")))) { + resizeRight(element); + IE7.Layout.boxSizing(element); + } + }; + IE7.Layout.fixRight = fixRight; + + function resizeRight(element) { + var left = getPixelWidth(element, element.runtimeStyle._left || element.currentStyle.left); + var width = layoutWidth(element) - getPixelWidth(element, element.currentStyle.right) - left - getWidth(element, "margin"); + if (parseInt(element.runtimeStyle.width) == width) return; + element.runtimeStyle.width = ""; + if (isFixed(element) || HEIGHT || element.offsetWidth < width) { + if (!quirksMode) width -= getBorderWidth(element) + getWidth(element, "padding"); + if (width < 0) width = 0; + element.runtimeStyle.fixedWidth = width; + setOverrideStyle(element, "width", width); + } + }; + + // ----------------------------------------------------------------------- + // window.onresize + // ----------------------------------------------------------------------- + + // handle window resize + var clientWidth = 0; + addResize(function() { + if (!viewport) return; + var i, wider = (clientWidth < viewport.clientWidth); + clientWidth = viewport.clientWidth; + // resize elements with "min-width" set + var elements = layout.minWidth.elements; + for (i in elements) { + var element = elements[i]; + var fixedWidth = (parseInt(element.runtimeStyle.width) == getFixedWidth(element, element.currentStyle.minWidth)); + if (wider && fixedWidth) element.runtimeStyle.width = ""; + if (wider == fixedWidth) resizeWidth(element); + } + // resize elements with "max-width" set + var elements = layout.maxWidth.elements; + for (i in elements) { + var element = elements[i]; + var fixedWidth = (parseInt(element.runtimeStyle.width) == getFixedWidth(element, element.currentStyle.maxWidth)); + if (!wider && fixedWidth) element.runtimeStyle.width = ""; + if (wider != fixedWidth) resizeWidth(element); + } + // resize elements with "right" set + for (i in fixRight.elements) resizeRight(fixRight.elements[i]); + }); + + // ----------------------------------------------------------------------- + // fix CSS + // ----------------------------------------------------------------------- + if (quirksMode) { + IE7.CSS.addRecalc("width", NUMERIC, applyWidth); + } + if (appVersion < 7) { + IE7.CSS.addRecalc("min-width", NUMERIC, layout.minWidth); + IE7.CSS.addRecalc("max-width", NUMERIC, layout.maxWidth); + IE7.CSS.addRecalc("right", NUMERIC, fixRight); + } + }; + + eval("var fixHeight=" + rotate(fixWidth)); + + // apply box-model + min/max fixes + fixWidth(); + fixHeight(true); +}; + +// ========================================================================= +// ie7-graphics.js +// ========================================================================= + +// a small transparent image used as a placeholder +var BLANK_GIF = makePath("blank.gif", path); + +var ALPHA_IMAGE_LOADER = "DXImageTransform.Microsoft.AlphaImageLoader"; +var PNG_FILTER = "progid:" + ALPHA_IMAGE_LOADER + "(src='%1',sizingMethod='%2')"; + +// regular expression version of the above +var PNG; + +var filtered = []; + +function fixImage(element) { + if (PNG.test(element.src)) { + // we have to preserve width and height + var image = new Image(element.width, element.height); + image.onload = function() { + element.width = image.width; + element.height = image.height; + image = null; + }; + image.src = element.src; + // store the original url (we'll put it back when it's printed) + element.pngSrc = element.src; + // add the AlphaImageLoader thingy + addFilter(element); + } +}; + +if (appVersion >= 5.5 && appVersion < 7) { + // ** IE7 VARIABLE + // e.g. only apply the hack to files ending in ".png" + // IE7_PNG_SUFFIX = ".png"; + + // replace background(-image): url(..) .. with background(-image): .. ;filter: ..; + IE7.CSS.addFix(/background(-image)?\s*:\s*([^};]*)?url\(([^\)]+)\)([^;}]*)?/, function(match, $1, $2, url, $4) { + url = getString(url); + return PNG.test(url) ? "filter:" + format(PNG_FILTER, url, "crop") + + ";zoom:1;background" + ($1||"") + ":" + ($2||"") + "none" + ($4||"") : match; + }); + + // ----------------------------------------------------------------------- + // fix PNG transparency (HTML images) + // ----------------------------------------------------------------------- + + IE7.HTML.addRecalc("img,input", function(element) { + if (element.tagName == "INPUT" && element.type != "image") return; + fixImage(element); + addEventHandler(element, "onpropertychange", function() { + if (!printing && event.propertyName == "src" && + element.src.indexOf(BLANK_GIF) == -1) fixImage(element); + }); + }); + + // assume that background images should not be printed + // (if they are not transparent then they'll just obscure content) + // but we'll put foreground images back... + var printing = false; + addEventHandler(window, "onbeforeprint", function() { + printing = true; + for (var i = 0; i < filtered.length; i++) removeFilter(filtered[i]); + }); + addEventHandler(window, "onafterprint", function() { + for (var i = 0; i < filtered.length; i++) addFilter(filtered[i]); + printing = false; + }); +} + +// apply a filter +function addFilter(element, sizingMethod) { + var filter = element.filters[ALPHA_IMAGE_LOADER]; + if (filter) { + filter.src = element.src; + filter.enabled = true; + } else { + element.runtimeStyle.filter = format(PNG_FILTER, element.src, sizingMethod || "scale"); + filtered.push(element); + } + // remove the real image + element.src = BLANK_GIF; +}; + +function removeFilter(element) { + element.src = element.pngSrc; + element.filters[ALPHA_IMAGE_LOADER].enabled = false; +}; + +// ========================================================================= +// ie7-fixed.js +// ========================================================================= + +new function(_) { + if (appVersion >= 7) return; + + // some things to consider for this hack. + // the document body requires a fixed background. even if + // it is just a blank image. + // you have to use setExpression instead of onscroll, this + // together with a fixed body background helps avoid the + // annoying screen flicker of other solutions. + + IE7.CSS.addRecalc("position", "fixed", _positionFixed, "absolute"); + IE7.CSS.addRecalc("background(-attachment)?", "[^};]*fixed", _backgroundFixed); + + // scrolling is relative to the documentElement (HTML tag) when in + // standards mode, otherwise it's relative to the document body + var $viewport = quirksMode ? "body" : "documentElement"; + + function _fixBackground() { + // this is required by both position:fixed and background-attachment:fixed. + // it is necessary for the document to also have a fixed background image. + // we can fake this with a blank image if necessary + if (body.currentStyle.backgroundAttachment != "fixed") { + if (body.currentStyle.backgroundImage == "none") { + body.runtimeStyle.backgroundRepeat = "no-repeat"; + body.runtimeStyle.backgroundImage = "url(" + BLANK_GIF + ")"; // dummy + } + body.runtimeStyle.backgroundAttachment = "fixed"; + } + _fixBackground = Undefined; + }; + + var _tmp = createTempElement("img"); + + function _isFixed(element) { + return element ? isFixed(element) || _isFixed(element.parentElement) : false; + }; + + function _setExpression(element, propertyName, expression) { + setTimeout("document.all." + element.uniqueID + ".runtimeStyle.setExpression('" + propertyName + "','" + expression + "')", 0); + }; + + // ----------------------------------------------------------------------- + // backgroundAttachment: fixed + // ----------------------------------------------------------------------- + + function _backgroundFixed(element) { + if (register(_backgroundFixed, element, element.currentStyle.backgroundAttachment == "fixed" && !element.contains(body))) { + _fixBackground(); + bgLeft(element); + bgTop(element); + _backgroundPosition(element); + } + }; + + function _backgroundPosition(element) { + _tmp.src = element.currentStyle.backgroundImage.slice(5, -2); + var parentElement = element.canHaveChildren ? element : element.parentElement; + parentElement.appendChild(_tmp); + setOffsetLeft(element); + setOffsetTop(element); + parentElement.removeChild(_tmp); + }; + + function bgLeft(element) { + element.style.backgroundPositionX = element.currentStyle.backgroundPositionX; + if (!_isFixed(element)) { + _setExpression(element, "backgroundPositionX", "(parseInt(runtimeStyle.offsetLeft)+document." + $viewport + ".scrollLeft)||0"); + } + }; + eval(rotate(bgLeft)); + + function setOffsetLeft(element) { + var propertyName = _isFixed(element) ? "backgroundPositionX" : "offsetLeft"; + element.runtimeStyle[propertyName] = + getOffsetLeft(element, element.style.backgroundPositionX) - + element.getBoundingClientRect().left - element.clientLeft + 2; + }; + eval(rotate(setOffsetLeft)); + + function getOffsetLeft(element, position) { + switch (position) { + case "left": + case "top": + return 0; + case "right": + case "bottom": + return viewport.clientWidth - _tmp.offsetWidth; + case "center": + return (viewport.clientWidth - _tmp.offsetWidth) / 2; + default: + if (PERCENT.test(position)) { + return parseInt((viewport.clientWidth - _tmp.offsetWidth) * parseFloat(position) / 100); + } + _tmp.style.left = position; + return _tmp.offsetLeft; + } + }; + eval(rotate(getOffsetLeft)); + + // ----------------------------------------------------------------------- + // position: fixed + // ----------------------------------------------------------------------- + + function _positionFixed(element) { + if (register(_positionFixed, element, isFixed(element))) { + setOverrideStyle(element, "position", "absolute"); + setOverrideStyle(element, "left", element.currentStyle.left); + setOverrideStyle(element, "top", element.currentStyle.top); + _fixBackground(); + IE7.Layout.fixRight(element); + _foregroundPosition(element); + } + }; + + function _foregroundPosition(element, recalc) { + positionTop(element, recalc); + positionLeft(element, recalc, true); + if (!element.runtimeStyle.autoLeft && element.currentStyle.marginLeft == "auto" && + element.currentStyle.right != "auto") { + var left = viewport.clientWidth - getPixelWidth(element, element.currentStyle.right) - + getPixelWidth(element, element.runtimeStyle._left) - element.clientWidth; + if (element.currentStyle.marginRight == "auto") left = parseInt(left / 2); + if (_isFixed(element.offsetParent)) element.runtimeStyle.pixelLeft += left; + else element.runtimeStyle.shiftLeft = left; + } + clipWidth(element); + clipHeight(element); + }; + + function clipWidth(element) { + var fixWidth = element.runtimeStyle.fixWidth; + element.runtimeStyle.borderRightWidth = ""; + element.runtimeStyle.width = fixWidth ? getPixelWidth(element, fixWidth) : ""; + if (element.currentStyle.width != "auto") { + var rect = element.getBoundingClientRect(); + var width = element.offsetWidth - viewport.clientWidth + rect.left - 2; + if (width >= 0) { + element.runtimeStyle.borderRightWidth = "0px"; + width = Math.max(getPixelValue(element, element.currentStyle.width) - width, 0); + setOverrideStyle(element, "width", width); + return width; + } + } + }; + eval(rotate(clipWidth)); + + function positionLeft(element, recalc) { + // if the element's width is in % units then it must be recalculated + // with respect to the viewport + if (!recalc && PERCENT.test(element.currentStyle.width)) { + element.runtimeStyle.fixWidth = element.currentStyle.width; + } + if (element.runtimeStyle.fixWidth) { + element.runtimeStyle.width = getPixelWidth(element, element.runtimeStyle.fixWidth); + } + //if (recalc) { + // // if the element is fixed on the right then no need to recalculate + // if (!element.runtimeStyle.autoLeft) return; + //} else { + element.runtimeStyle.shiftLeft = 0; + element.runtimeStyle._left = element.currentStyle.left; + // is the element fixed on the right? + element.runtimeStyle.autoLeft = element.currentStyle.right != "auto" && + element.currentStyle.left == "auto"; + //} + // reset the element's "left" value and get it's natural position + element.runtimeStyle.left = ""; + element.runtimeStyle.screenLeft = getScreenLeft(element); + element.runtimeStyle.pixelLeft = element.runtimeStyle.screenLeft; + // if the element is contained by another fixed element then there is no need to + // continually recalculate it's left position + if (!recalc && !_isFixed(element.offsetParent)) { + // onsrcoll produces jerky movement, so we use an expression + _setExpression(element, "pixelLeft", "runtimeStyle.screenLeft+runtimeStyle.shiftLeft+document." + $viewport + ".scrollLeft"); + } + }; + // clone this function so we can do "top" + eval(rotate(positionLeft)); + + // I've forgotten how this works... + function getScreenLeft(element) { // thanks to kevin newman (captainn) + var screenLeft = element.offsetLeft, nested = 1; + if (element.runtimeStyle.autoLeft) { + screenLeft = viewport.clientWidth - element.offsetWidth - getPixelWidth(element, element.currentStyle.right); + } + // accommodate margins + if (element.currentStyle.marginLeft != "auto") { + screenLeft -= getPixelWidth(element, element.currentStyle.marginLeft); + } + while (element = element.offsetParent) { + if (element.currentStyle.position != "static") nested = -1; + screenLeft += element.offsetLeft * nested; + } + return screenLeft; + }; + eval(rotate(getScreenLeft)); + + function getPixelWidth(element, value) { + return PERCENT.test(value) ? parseInt(parseFloat(value) / 100 * viewport.clientWidth) : getPixelValue(element, value); + }; + eval(rotate(getPixelWidth)); + + // ----------------------------------------------------------------------- + // capture window resize + // ----------------------------------------------------------------------- + + function _resize() { + // if the window has been resized then some positions need to be + // recalculated (especially those aligned to "right" or "top" + var elements = _backgroundFixed.elements; + for (var i in elements) _backgroundPosition(elements[i]); + elements = _positionFixed.elements; + for (i in elements) { + _foregroundPosition(elements[i], true); + // do this twice to be sure - hackish, I know :-) + _foregroundPosition(elements[i], true); + } + _timer = 0; + }; + + // use a timer for some reason. + // (sometimes this is a good way to prevent resize loops) + var _timer; + addResize(function() { + if (!_timer) _timer = setTimeout(_resize, 0); + }); +}; + +// ========================================================================= +// ie7-oveflow.js +// ========================================================================= + +/* --------------------------------------------------------------------- + + This module alters the structure of the document. + It may adversely affect other CSS rules. Be warned. + +--------------------------------------------------------------------- */ + +var WRAPPER_STYLE = { + backgroundColor: "transparent", + backgroundImage: "none", + backgroundPositionX: null, + backgroundPositionY: null, + backgroundRepeat: null, + borderTopWidth: 0, + borderRightWidth: 0, + borderBottomWidth: 0, + borderLeftStyle: "none", + borderTopStyle: "none", + borderRightStyle: "none", + borderBottomStyle: "none", + borderLeftWidth: 0, + height: null, + marginTop: 0, + marginBottom: 0, + marginRight: 0, + marginLeft: 0, + width: "100%" +}; + +IE7.CSS.addRecalc("overflow", "visible", function(element) { + // don't do this again + if (element.parentNode.ie7_wrapped) return; + + // if max-height is applied, makes sure it gets applied first + if (IE7.Layout && element.currentStyle["max-height"] != "auto") { + IE7.Layout.maxHeight(element); + } + + if (element.currentStyle.marginLeft == "auto") element.style.marginLeft = 0; + if (element.currentStyle.marginRight == "auto") element.style.marginRight = 0; + + var wrapper = document.createElement(ANON); + wrapper.ie7_wrapped = element; + for (var propertyName in WRAPPER_STYLE) { + wrapper.style[propertyName] = element.currentStyle[propertyName]; + if (WRAPPER_STYLE[propertyName] != null) { + element.runtimeStyle[propertyName] = WRAPPER_STYLE[propertyName]; + } + } + wrapper.style.display = "block"; + wrapper.style.position = "relative"; + element.runtimeStyle.position = "absolute"; + element.parentNode.insertBefore(wrapper, element); + wrapper.appendChild(element); +}); + +// ========================================================================= +// ie7-quirks.js +// ========================================================================= + +function ie7Quirks() { + var FONT_SIZES = "xx-small,x-small,small,medium,large,x-large,xx-large".split(","); + for (var i = 0; i < FONT_SIZES.length; i++) { + FONT_SIZES[FONT_SIZES[i]] = FONT_SIZES[i - 1] || "0.67em"; + } + + IE7.CSS.addFix(/(font(-size)?\s*:\s*)([\w.-]+)/, function(match, label, size, value) { + return label + (FONT_SIZES[value] || value); + }); + + if (appVersion < 6) { + var NEGATIVE = /^\-/, LENGTH = /(em|ex)$/i; + var EM = /em$/i, EX = /ex$/i; + + getPixelValue = function(element, value) { + if (PIXEL.test(value)) return parseInt(value)||0; + var scale = NEGATIVE.test(value)? -1 : 1; + if (LENGTH.test(value)) scale *= getFontScale(element); + temp.style.width = (scale < 0) ? value.slice(1) : value; + body.appendChild(temp); + // retrieve pixel width + value = scale * temp.offsetWidth; + // remove the temporary element + temp.removeNode(); + return parseInt(value); + }; + + var temp = createTempElement(); + function getFontScale(element) { + var scale = 1; + temp.style.fontFamily = element.currentStyle.fontFamily; + temp.style.lineHeight = element.currentStyle.lineHeight; + //temp.style.fontSize = ""; + while (element != body) { + var fontSize = element.currentStyle["ie7-font-size"]; + if (fontSize) { + if (EM.test(fontSize)) scale *= parseFloat(fontSize); + else if (PERCENT.test(fontSize)) scale *= (parseFloat(fontSize) / 100); + else if (EX.test(fontSize)) scale *= (parseFloat(fontSize) / 2); + else { + temp.style.fontSize = fontSize; + return 1; + } + } + element = element.parentElement; + } + return scale; + }; + + // cursor:pointer (IE5.x) + IE7.CSS.addFix(/cursor\s*:\s*pointer/, "cursor:hand"); + // display:list-item (IE5.x) + IE7.CSS.addFix(/display\s*:\s*list-item/, "display:block"); + } + + // ----------------------------------------------------------------------- + // margin:auto + // ----------------------------------------------------------------------- + + function fixMargin(element) { + if (appVersion < 5.5) IE7.Layout.boxSizing(element.parentElement); + var parent = element.parentElement; + var margin = parent.offsetWidth - element.offsetWidth - getPaddingWidth(parent); + var autoRight = (element.currentStyle["ie7-margin"] && element.currentStyle.marginRight == "auto") || + element.currentStyle["ie7-margin-right"] == "auto"; + switch (parent.currentStyle.textAlign) { + case "right": + margin = autoRight ? parseInt(margin / 2) : 0; + element.runtimeStyle.marginRight = margin + "px"; + break; + case "center": + if (autoRight) margin = 0; + default: + if (autoRight) margin /= 2; + element.runtimeStyle.marginLeft = parseInt(margin) + "px"; + } + }; + + function getPaddingWidth(element) { + return getPixelValue(element, element.currentStyle.paddingLeft) + + getPixelValue(element, element.currentStyle.paddingRight); + }; + + IE7.CSS.addRecalc("margin(-left|-right)?", "[^};]*auto", function(element) { + if (register(fixMargin, element, + element.parentElement && + element.currentStyle.display == "block" && + element.currentStyle.marginLeft == "auto" && + element.currentStyle.position != "absolute")) { + fixMargin(element); + } + }); + + addResize(function() { + for (var i in fixMargin.elements) { + var element = fixMargin.elements[i]; + element.runtimeStyle.marginLeft = + element.runtimeStyle.marginRight = ""; + fixMargin(element); + } + }); +}; + + +// ----------------------------------------------------------------------- +// initialisation +// ----------------------------------------------------------------------- + +IE7.loaded = true; + +(function() { + try { + // http://javascript.nwbox.com/IEContentLoaded/ + documentElement.doScroll("left"); + } catch (e) { + setTimeout(arguments.callee, 1); + return; + } + // execute the inner text of the IE7 script + try { + eval(script.innerHTML); + } catch (e) { + // ignore errors + } + PNG = new RegExp(rescape(typeof IE7_PNG_SUFFIX == "string" ? IE7_PNG_SUFFIX : "-trans.png") + "$", "i"); + + // frequently used references + body = document.body; + viewport = quirksMode ? body : documentElement; + + // classes + body.className += " ie7_body"; + documentElement.className += " ie7_html"; + + if (quirksMode) ie7Quirks(); + + IE7.CSS.init(); + IE7.HTML.init(); + + IE7.HTML.apply(); + IE7.CSS.apply(); + + IE7.recalc(); +})(); + + +})(); diff --git a/lib/galaxy/webapps/reports/static/scripts/IE8.js b/lib/galaxy/webapps/reports/static/scripts/IE8.js new file mode 100644 index 00000000000..cadc72345b5 --- /dev/null +++ b/lib/galaxy/webapps/reports/static/scripts/IE8.js @@ -0,0 +1,2601 @@ +// timestamp: Sun, 03 Feb 2008 19:26:22 +/* + IE7/IE8.js - copyright 2004-2008, Dean Edwards + http://dean.edwards.name/IE7/ + http://www.opensource.org/licenses/mit-license.php +*/ + +/* W3C compliance for Microsoft Internet Explorer */ + +/* credits/thanks: + Shaggy, Martijn Wargers, Jimmy Cerra, Mark D Anderson, + Lars Dieckow, Erik Arvidsson, Gellért Gyuris, James Denny, + Unknown W Brackets, Benjamin Westfarer, Rob Eberhardt, + Bill Edney, Kevin Newman, James Crompton, Matthew Mastracci, + Doug Wright, Richard York, Kenneth Kolano, MegaZone, + Thomas Verelst, Mark 'Tarquin' Wilton-Jones, Rainer Åhlfors, + David Zulaica, Ken Kolano, Kevin Newman +*/ + +// ======================================================================= +// TO DO +// ======================================================================= + +// PNG - unclickable content + +// ======================================================================= +// TEST/BUGGY +// ======================================================================= + +// hr{margin:1em auto} (doesn't look right in IE5) + +(function() { + +IE7 = { + toString: function(){return "IE7 version 2.0 (beta3)"} +}; +var appVersion = IE7.appVersion = navigator.appVersion.match(/MSIE (\d\.\d)/)[1]; + +if (/ie7_off/.test(top.location.search) || appVersion < 5) return; + +var Undefined = K(); +var quirksMode = document.compatMode != "CSS1Compat"; +var documentElement = document.documentElement, body, viewport; +var ANON = "!"; +var HEADER = ":link{ie7-link:link}:visited{ie7-link:visited}"; + +// ----------------------------------------------------------------------- +// external +// ----------------------------------------------------------------------- + +var RELATIVE = /^[\w\.]+[^:]*$/; +function makePath(href, path) { + if (RELATIVE.test(href)) href = (path || "") + href; + return href; +}; + +function getPath(href, path) { + href = makePath(href, path); + return href.slice(0, href.lastIndexOf("/") + 1); +}; + +// get the path to this script +var script = document.scripts[document.scripts.length - 1]; +var path = getPath(script.src); + +// we'll use microsoft's http request object to load external files +try { + var httpRequest = new ActiveXObject("Microsoft.XMLHTTP"); +} catch (e) { + // ActiveX disabled +} + +var fileCache = {}; +function loadFile(href, path) { +try { + href = makePath(href, path); + if (!fileCache[href]) { + // easy to load a file huh? + httpRequest.open("GET", href, false); + httpRequest.send(); + if (httpRequest.status == 0 || httpRequest.status == 200) { + fileCache[href] = httpRequest.responseText; + } + } +} catch (e) { + // ignore errors +} finally { + return fileCache[href] || ""; +}}; + +// ----------------------------------------------------------------------- +// IE5.0 compatibility +// ----------------------------------------------------------------------- + + +if (appVersion < 5.5) { + undefined = Undefined(); + + ANON = "HTML:!"; // for anonymous content + + // Fix String.replace (Safari1.x/IE5.0). + var GLOBAL = /(g|gi)$/; + var _String_replace = String.prototype.replace; + String.prototype.replace = function(expression, replacement) { + if (typeof replacement == "function") { // Safari doesn't like functions + if (expression && expression.constructor == RegExp) { + var regexp = expression; + var global = regexp.global; + if (global == null) global = GLOBAL.test(regexp); + // we have to convert global RexpExps for exec() to work consistently + if (global) regexp = new RegExp(regexp.source); // non-global + } else { + regexp = new RegExp(rescape(expression)); + } + var match, string = this, result = ""; + while (string && (match = regexp.exec(string))) { + result += string.slice(0, match.index) + replacement.apply(this, match); + string = string.slice(match.index + match[0].length); + if (!global) break; + } + return result + string; + } + return _String_replace.apply(this, arguments); + }; + + Array.prototype.pop = function() { + if (this.length) { + var i = this[this.length - 1]; + this.length--; + return i; + } + return undefined; + }; + + Array.prototype.push = function() { + for (var i = 0; i < arguments.length; i++) { + this[this.length] = arguments[i]; + } + return this.length; + }; + + var ns = this; + Function.prototype.apply = function(o, a) { + if (o === undefined) o = ns; + else if (o == null) o = window; + else if (typeof o == "string") o = new String(o); + else if (typeof o == "number") o = new Number(o); + else if (typeof o == "boolean") o = new Boolean(o); + if (arguments.length == 1) a = []; + else if (a[0] && a[0].writeln) a[0] = a[0].documentElement.document || a[0]; + var $ = "#ie7_apply", r; + o[$] = this; + switch (a.length) { // unroll for speed + case 0: r = o[$](); break; + case 1: r = o[$](a[0]); break; + case 2: r = o[$](a[0],a[1]); break; + case 3: r = o[$](a[0],a[1],a[2]); break; + case 4: r = o[$](a[0],a[1],a[2],a[3]); break; + case 5: r = o[$](a[0],a[1],a[2],a[3],a[4]); break; + default: + var b = [], i = a.length - 1; + do b[i] = "a[" + i + "]"; while (i--); + eval("r=o[$](" + b + ")"); + } + if (typeof o.valueOf == "function") { // not a COM object + delete o[$]; + } else { + o[$] = undefined; + if (r && r.writeln) r = r.documentElement.document || r; + } + return r; + }; + + Function.prototype.call = function(o) { + return this.apply(o, _slice.apply(arguments, [1])); + }; + + // block elements are "inline" according to IE5.0 so we'll fix it + HEADER += "address,blockquote,body,dd,div,dt,fieldset,form,"+ + "frame,frameset,h1,h2,h3,h4,h5,h6,iframe,noframes,object,p,"+ + "hr,applet,center,dir,menu,pre,dl,li,ol,ul{display:block}"; +} + +// ----------------------------------------------------------------------- +// OO support +// ----------------------------------------------------------------------- + + +// This is a cut-down version of base2 (http://code.google.com/p/base2/) + +var _slice = Array.prototype.slice; + +// private +var _FORMAT = /%([1-9])/g; +var _LTRIM = /^\s\s*/; +var _RTRIM = /\s\s*$/; +var _RESCAPE = /([\/()[\]{}|*+-.,^$?\\])/g; // safe regular expressions +var _BASE = /\bbase\b/; +var _HIDDEN = ["constructor", "toString"]; // only override these when prototyping + +var prototyping; + +function Base(){}; +Base.extend = function(_instance, _static) { + // Build the prototype. + prototyping = true; + var _prototype = new this; + extend(_prototype, _instance); + prototyping = false; + + // Create the wrapper for the constructor function. + var _constructor = _prototype.constructor; + function klass() { + // Don't call the constructor function when prototyping. + if (!prototyping) _constructor.apply(this, arguments); + }; + _prototype.constructor = klass; + + // Build the static interface. + klass.extend = arguments.callee; + extend(klass, _static); + klass.prototype = _prototype; + return klass; +}; +Base.prototype.extend = function(source) { + return extend(this, source); +}; + +// A collection of regular expressions and their associated replacement values. +// A Base class for creating parsers. + +var _HASH = "#"; +var _KEYS = "~"; + +var _RG_ESCAPE_CHARS = /\\./g; +var _RG_ESCAPE_BRACKETS = /\(\?[:=!]|\[[^\]]+\]/g; +var _RG_BRACKETS = /\(/g; + +var RegGrp = Base.extend({ + constructor: function(values) { + this[_KEYS] = []; + this.merge(values); + }, + + exec: function(string) { + var items = this, keys = this[_KEYS]; + return String(string).replace(new RegExp(this, this.ignoreCase ? "gi" : "g"), function() { + var item, offset = 1, i = 0; + // Loop through the RegGrp items. + while ((item = items[_HASH + keys[i++]])) { + var next = offset + item.length + 1; + if (arguments[offset]) { // do we have a result? + var replacement = item.replacement; + switch (typeof replacement) { + case "function": + return replacement.apply(items, _slice.call(arguments, offset, next)); + case "number": + return arguments[offset + replacement]; + default: + return replacement; + } + } + offset = next; + } + }); + }, + + add: function(expression, replacement) { + if (expression instanceof RegExp) { + expression = expression.source; + } + if (!this[_HASH + expression]) this[_KEYS].push(String(expression)); + this[_HASH + expression] = new RegGrp.Item(expression, replacement); + }, + + merge: function(values) { + for (var i in values) this.add(i, values[i]); + }, + + toString: function() { + // back references not supported in simple RegGrp + return "(" + this[_KEYS].join(")|(") + ")"; + } +}, { + IGNORE: "$0", + + Item: Base.extend({ + constructor: function(expression, replacement) { + expression = expression instanceof RegExp ? expression.source : String(expression); + + if (typeof replacement == "number") replacement = String(replacement); + else if (replacement == null) replacement = ""; + + // does the pattern use sub-expressions? + if (typeof replacement == "string" && /\$(\d+)/.test(replacement)) { + // a simple lookup? (e.g. "$2") + if (/^\$\d+$/.test(replacement)) { + // store the index (used for fast retrieval of matched strings) + replacement = parseInt(replacement.slice(1)); + } else { // a complicated lookup (e.g. "Hello $2 $1") + // build a function to do the lookup + var Q = /'/.test(replacement.replace(/\\./g, "")) ? '"' : "'"; + replacement = replacement.replace(/\n/g, "\\n").replace(/\r/g, "\\r").replace(/\$(\d+)/g, Q + + "+(arguments[$1]||" + Q+Q + ")+" + Q); + replacement = new Function("return " + Q + replacement.replace(/(['"])\1\+(.*)\+\1\1$/, "$1") + Q); + } + } + + this.length = RegGrp.count(expression); + this.replacement = replacement; + this.toString = K(expression); + } + }), + + count: function(expression) { + // Count the number of sub-expressions in a RegExp/RegGrp.Item. + expression = String(expression).replace(_RG_ESCAPE_CHARS, "").replace(_RG_ESCAPE_BRACKETS, ""); + return match(expression, _RG_BRACKETS).length; + } +}); + +// ========================================================================= +// lang/extend.js +// ========================================================================= + +function extend(object, source) { // or extend(object, key, value) + if (object && source) { + var proto = (typeof source == "function" ? Function : Object).prototype; + // Add constructor, toString etc + var i = _HIDDEN.length, key; + if (prototyping) while (key = _HIDDEN[--i]) { + var value = source[key]; + if (value != proto[key]) { + if (_BASE.test(value)) { + _override(object, key, value) + } else { + object[key] = value; + } + } + } + // Copy each of the source object's properties to the target object. + for (key in source) if (proto[key] === undefined) { + var value = source[key]; + // Check for method overriding. + if (object[key] && typeof value == "function" && _BASE.test(value)) { + _override(object, key, value); + } else { + object[key] = value; + } + } + } + return object; +}; + +function _override(object, name, method) { + // Override an existing method. + var ancestor = object[name]; + object[name] = function() { + var previous = this.base; + this.base = ancestor; + var returnValue = method.apply(this, arguments); + this.base = previous; + return returnValue; + }; +}; + +function combine(keys, values) { + // Combine two arrays to make a hash. + if (!values) values = keys; + var hash = {}; + for (var i in keys) hash[i] = values[i]; + return hash; +}; + +function format(string) { + // Replace %n with arguments[n]. + // e.g. format("%1 %2%3 %2a %1%3", "she", "se", "lls"); + // ==> "she sells sea shells" + // Only %1 - %9 supported. + var args = arguments; + var _FORMAT = new RegExp("%([1-" + arguments.length + "])", "g"); + return String(string).replace(_FORMAT, function(match, index) { + return index < args.length ? args[index] : match; + }); +}; + +function match(string, expression) { + // Same as String.match() except that this function will return an empty + // array if there is no match. + return String(string).match(expression) || []; +}; + +function rescape(string) { + // Make a string safe for creating a RegExp. + return String(string).replace(_RESCAPE, "\\$1"); +}; + +// http://blog.stevenlevithan.com/archives/faster-trim-javascript +function trim(string) { + return String(string).replace(_LTRIM, "").replace(_RTRIM, ""); +}; + +function K(k) { + return function() { + return k; + }; +}; + +// ----------------------------------------------------------------------- +// parsing +// ----------------------------------------------------------------------- + +var Parser = RegGrp.extend({ignoreCase: true}); + +var ENCODED = /\x01(\d+)/g, + QUOTES = /'/g, + STRING = /^\x01/, + UNICODE = /\\([\da-fA-F]{1,4})/g; + +var _strings = []; + +var encoder = new Parser({ + // comments + "": "", + "\\/\\*[^*]*\\*+([^\\/][^*]*\\*+)*\\/": "", + // get rid + "@(namespace|import)[^;\\n]+[;\\n]": "", + // strings + "'(\\\\.|[^'\\\\])*'": encodeString, + '"(\\\\.|[^"\\\\])*"': encodeString, + // white space + "\\s+": " " +}); + +function encode(cssText) { + return encoder.exec(cssText); +}; + +function decode(cssText) { + return cssText.replace(ENCODED, function(match, index) { + return _strings[index - 1]; + }); +}; + +function encodeString(string) { + return "\x01" + _strings.push(string.replace(UNICODE, function(match, chr) { + return eval("'\\u" + "0000".slice(chr.length) + chr + "'"); + }).slice(1, -1).replace(QUOTES, "\\'")); +}; + +function getString(value) { + return STRING.test(value) ? _strings[value.slice(1) - 1] : value; +}; + +// clone a "width" function to create a "height" function +var rotater = new RegGrp({ + Width: "Height", + width: "height", + Left: "Top", + left: "top", + Right: "Bottom", + right: "bottom", + onX: "onY" +}); + +function rotate(fn) { + return rotater.exec(fn); +}; + +// ----------------------------------------------------------------------- +// event handling +// ----------------------------------------------------------------------- + +var eventHandlers = []; + +function addResize(handler) { + addRecalc(handler); + addEventHandler(window, "onresize", handler); +}; + +// add an event handler (function) to an element +function addEventHandler(element, type, handler) { + element.attachEvent(type, handler); + // store the handler so it can be detached later + eventHandlers.push(arguments); +}; + +// remove an event handler assigned to an element by IE7 +function removeEventHandler(element, type, handler) { +try { + element.detachEvent(type, handler); +} catch (ignore) { + // write a letter of complaint to microsoft.. +}}; + +// remove event handlers (they eat memory) +addEventHandler(window, "onunload", function() { + var handler; + while (handler = eventHandlers.pop()) { + removeEventHandler(handler[0], handler[1], handler[2]); + } +}); + +function register(handler, element, condition) { // -@DRE + //var set = handler[element.uniqueID]; + if (!handler.elements) handler.elements = {}; + if (condition) handler.elements[element.uniqueID] = element; + else delete handler.elements[element.uniqueID]; + //return !set && condition; + return condition; +}; + +addEventHandler(window, "onbeforeprint", function() { + if (!IE7.CSS.print) new StyleSheet("print"); + IE7.CSS.print.recalc(); +}); + +// ----------------------------------------------------------------------- +// pixel conversion +// ----------------------------------------------------------------------- + +// this is handy because it means that web developers can mix and match +// measurement units in their style sheets. it is not uncommon to +// express something like padding in "em" units whilst border thickness +// is most often expressed in pixels. + +var PIXEL = /^\d+(px)?$/i; +var PERCENT = /^\d+%$/; +var getPixelValue = function(element, value) { + if (PIXEL.test(value)) return parseInt(value); + var style = element.style.left; + var runtimeStyle = element.runtimeStyle.left; + element.runtimeStyle.left = element.currentStyle.left; + element.style.left = value || 0; + value = element.style.pixelLeft; + element.style.left = style; + element.runtimeStyle.left = runtimeStyle; + return value; +}; + +// ----------------------------------------------------------------------- +// generic +// ----------------------------------------------------------------------- + +var $IE7 = "ie7-"; + +var Fix = Base.extend({ + constructor: function() { + this.fixes = []; + this.recalcs = []; + }, + init: Undefined +}); + +// a store for functions that will be called when refreshing IE7 +var recalcs = []; +function addRecalc(recalc) { + recalcs.push(recalc); +}; + +IE7.recalc = function() { + IE7.HTML.recalc(); + // re-apply style sheet rules (re-calculate ie7 classes) + IE7.CSS.recalc(); + // apply global fixes to the document + for (var i = 0; i < recalcs.length; i++) recalcs[i](); +}; + +function isFixed(element) { + return element.currentStyle["ie7-position"] == "fixed"; +}; + +// original style +function getDefinedStyle(element, propertyName) { + return element.currentStyle[$IE7 + propertyName] || element.currentStyle[propertyName]; +}; + +function setOverrideStyle(element, propertyName, value) { + if (element.currentStyle[$IE7 + propertyName] == null) { + element.runtimeStyle[$IE7 + propertyName] = element.currentStyle[propertyName]; + } + element.runtimeStyle[propertyName] = value; +}; + +// create a temporary element which is used to inherit styles +// from the target element. the temporary element can be resized +// to determine pixel widths/heights +function createTempElement(tagName) { + var element = document.createElement(tagName || "object"); + element.style.cssText = "position:absolute;padding:0;display:block;border:none;clip:rect(0 0 0 0);left:-9999"; + element.ie7_anon = true; + return element; +}; + + +// ========================================================================= +// ie7-cssQuery.js +// ========================================================================= + +function cssQuery(selector, context, single) { + if (!_cache[selector]) { + reg = []; // store for RegExp objects + var fn = ""; + var selectors = cssParser.escape(selector).split(","); + for (var i = 0; i < selectors.length; i++) { + _wild = _index = _list = 0; // reset + _duplicate = selectors.length > 1 ? 2 : 0; // reset + var block = cssParser.exec(selectors[i]) || "if(0){"; + if (_wild) { // IE's pesky comment nodes + block += format("if(e%1.nodeName!='!'){", _index); + } + // check for duplicates before storing results + var store = _duplicate > 1 ? _TEST : ""; + block += format(store + _STORE, _index); + // add closing braces + block += Array(match(block, /\{/g).length + 1).join("}"); + fn += block; + } + eval(format(_FN, reg) + cssParser.unescape(fn) + "return s?null:r}"); + _cache[selector] = _selectorFunction; + } + return _cache[selector](context || document, single); +}; + +var _MSIE5 = appVersion < 6; + +var _EVALUATED = /^(href|src)$/; +var _ATTRIBUTES = { + "class": "className", + "for": "htmlFor" +}; + +IE7._indexed = 1; + +IE7._byId = function(document, id) { + var result = document.all[id] || null; + // returns a single element or a collection + if (!result || result.id == id) return result; + // document.all has returned a collection of elements with name/id + for (var i = 0; i < result.length; i++) { + if (result[i].id == id) return result[i]; + } + return null; +}; + +IE7._getAttribute = function(element, name) { + if (name == "src" && element.pngSrc) return element.pngSrc; + + var attribute = _MSIE5 ? (element.attributes[name] || element.attributes[_ATTRIBUTES[name.toLowerCase()]]) : element.getAttributeNode(name); + if (attribute && (attribute.specified || name == "value")) { + if (_EVALUATED.test(name)) { + return element.getAttribute(name, 2); + } else if (name == "class") { + return element.className.replace(/\sie7_\w+/g, ""); + } else if (name == "style") { + return element.style.cssText; + } else { + return attribute.nodeValue; + } + } + return null; +}; + +var names = "colSpan,rowSpan,vAlign,dateTime,accessKey,tabIndex,encType,maxLength,readOnly,longDesc"; +// Convert the list of strings to a hash, mapping the lowercase name to the camelCase name. +extend(_ATTRIBUTES, combine(names.toLowerCase().split(","), names.split(","))); + +IE7._getNextElementSibling = function(node) { + // return the next element to the supplied element + // nextSibling is not good enough as it might return a text or comment node + while (node && (node = node.nextSibling) && (node.nodeType != 1 || node.nodeName == "!")) continue; + return node; +}; + +IE7._getPreviousElementSibling = function(node) { + // return the previous element to the supplied element + while (node && (node = node.previousSibling) && (node.nodeType != 1 || node.nodeName == "!")) continue; + return node; +}; + +// ========================================================================= +// CSSParser +// ========================================================================= + +var IMPLIED_ASTERISK = /([\s>+~,]|[^(]\+|^)([#.:\[])/g, + IMPLIED_SPACE = /(^|,)([^\s>+~])/g, + WHITESPACE = /\s*([\s>+~(),]|^|$)\s*/g, + WILD_CARD = /\s\*\s/g;; + +var CSSParser = RegGrp.extend({ + constructor: function(items) { + this.base(items); + this.sorter = new RegGrp; + this.sorter.add(/:not\([^)]*\)/, RegGrp.IGNORE); + this.sorter.add(/([ >](\*|[\w-]+))([^: >+~]*)(:\w+-child(\([^)]+\))?)([^: >+~]*)/, "$1$3$6$4"); + }, + + ignoreCase: true, + + escape: function(selector) { + return this.optimise(this.format(selector)); + }, + + format: function(selector) { + return selector + .replace(WHITESPACE, "$1") + .replace(IMPLIED_SPACE, "$1 $2") + .replace(IMPLIED_ASTERISK, "$1*$2"); + }, + + optimise: function(selector) { + // optimise wild card descendant selectors + return this.sorter.exec(selector.replace(WILD_CARD, ">* ")); + }, + + unescape: function(selector) { + return decode(selector); + } +}); + +// some constants +var _OPERATORS = { + "": "%1!=null", + "=": "%1=='%2'", + "~=": /(^| )%1( |$)/, + "|=": /^%1(-|$)/, + "^=": /^%1/, + "$=": /%1$/, + "*=": /%1/ +}; + +var _PSEUDO_CLASSES = { + "first-child": "!IE7._getPreviousElementSibling(e%1)", + "link": "e%1.currentStyle['ie7-link']=='link'", + "visited": "e%1.currentStyle['ie7-link']=='visited'" +}; + +var _VAR = "var p%2=0,i%2,e%2,n%2=e%1."; +var _ID = "e%1.sourceIndex"; +var _TEST = "var g=" + _ID + ";if(!p[g]){p[g]=1;"; +var _STORE = "r[r.length]=e%1;if(s)return e%1;"; +var _FN = "var _selectorFunction=function(e0,s){IE7._indexed++;var r=[],p={},reg=[%1],d=document;"; +var reg; // a store for RexExp objects +var _index; +var _wild; // need to flag certain _wild card selectors as MSIE includes comment nodes +var _list; // are we processing a node _list? +var _duplicate; // possible duplicates? +var _cache = {}; // store parsed selectors + +// a hideous parser +var cssParser = new CSSParser({ + " (\\*|[\\w-]+)#([\\w-]+)": function(match, tagName, id) { // descendant selector followed by ID + _wild = false; + var replacement = "var e%2=IE7._byId(d,'%4');if(e%2&&"; + if (tagName != "*") replacement += "e%2.nodeName=='%3'&&"; + replacement += "(e%1==d||e%1.contains(e%2))){"; + if (_list) replacement += format("i%1=n%1.length;", _list); + return format(replacement, _index++, _index, tagName.toUpperCase(), id); + }, + + " (\\*|[\\w-]+)": function(match, tagName) { // descendant selector + _duplicate++; // this selector may produce duplicates + _wild = tagName == "*"; + var replacement = _VAR; + // IE5.x does not support getElementsByTagName("*"); + replacement += (_wild && _MSIE5) ? "all" : "getElementsByTagName('%3')"; + replacement += ";for(i%2=0;(e%2=n%2[i%2]);i%2++){"; + return format(replacement, _index++, _list = _index, tagName.toUpperCase()); + }, + + ">(\\*|[\\w-]+)": function(match, tagName) { // child selector + var children = _list; + _wild = tagName == "*"; + var replacement = _VAR; + // use the children property for MSIE as it does not contain text nodes + // (but the children collection still includes comments). + // the document object does not have a children collection + replacement += children ? "children": "childNodes"; + if (!_wild && children) replacement += ".tags('%3')"; + replacement += ";for(i%2=0;(e%2=n%2[i%2]);i%2++){"; + if (_wild) { + replacement += "if(e%2.nodeType==1){"; + _wild = _MSIE5; + } else { + if (!children) replacement += "if(e%2.nodeName=='%3'){"; + } + return format(replacement, _index++, _list = _index, tagName.toUpperCase()); + }, + + "\\+(\\*|[\\w-]+)": function(match, tagName) { // direct adjacent selector + var replacement = ""; + if (_wild) replacement += "if(e%1.nodeName!='!'){"; + _wild = false; + replacement += "e%1=IE7._getNextElementSibling(e%1);if(e%1"; + if (tagName != "*") replacement += "&&e%1.nodeName=='%2'"; + replacement += "){"; + return format(replacement, _index, tagName.toUpperCase()); + }, + + "~(\\*|[\\w-]+)": function(match, tagName) { // indirect adjacent selector + var replacement = ""; + if (_wild) replacement += "if(e%1.nodeName!='!'){"; + _wild = false; + _duplicate = 2; // this selector may produce duplicates + replacement += "while(e%1=e%1.nextSibling){if(e%1.ie7_adjacent==IE7._indexed)break;if("; + if (tagName == "*") { + replacement += "e%1.nodeType==1"; + if (_MSIE5) replacement += "&&e%1.nodeName!='!'"; + } else replacement += "e%1.nodeName=='%2'"; + replacement += "){e%1.ie7_adjacent=IE7._indexed;"; + return format(replacement, _index, tagName.toUpperCase()); + }, + + "#([\\w-]+)": function(match, id) { // ID selector + _wild = false; + var replacement = "if(e%1.id=='%2'){"; + if (_list) replacement += format("i%1=n%1.length;", _list); + return format(replacement, _index, id); + }, + + "\\.([\\w-]+)": function(match, className) { // class selector + _wild = false; + // store RegExp objects - slightly faster on IE + reg.push(new RegExp("(^|\\s)" + rescape(className) + "(\\s|$)")); + return format("if(e%1.className&®[%2].test(e%1.className)){", _index, reg.length - 1); + }, + + "\\[([\\w-]+)\\s*([^=]?=)?\\s*([^\\]]*)\\]": function(match, attr, operator, value) { // attribute selectors + var alias = _ATTRIBUTES[attr] || attr; + if (operator) { + var getAttribute = "e%1.getAttribute('%2',2)"; + if (!_EVALUATED.test(attr)) { + getAttribute = "e%1.%3||" + getAttribute; + } + attr = format("(" + getAttribute + ")", _index, attr, alias); + } else { + attr = format("IE7._getAttribute(e%1,'%2')", _index, attr); + } + var replacement = _OPERATORS[operator || ""] || "0"; + if (replacement && replacement.source) { + reg.push(new RegExp(format(replacement.source, rescape(cssParser.unescape(value))))); + replacement = "reg[%2].test(%1)"; + value = reg.length - 1; + } + return "if(" + format(replacement, attr, value) + "){"; + }, + + ":+([\\w-]+)(\\(([^)]+)\\))?": function(match, pseudoClass, $2, args) { // pseudo class selectors + pseudoClass = _PSEUDO_CLASSES[pseudoClass]; + return "if(" + (pseudoClass ? format(pseudoClass, _index, args || "") : "0") + "){"; + } +}); + +// ========================================================================= +// ie7-css.js +// ========================================================================= + +var HYPERLINK = /a(#[\w-]+)?(\.[\w-]+)?:(hover|active)/i; +var BRACE1 = /\s*\{\s*/, BRACE2 = /\s*\}\s*/, COMMA = /\s*\,\s*/; +var FIRST_LINE_LETTER = /(.*)(:first-(line|letter))/; + +//var UNKNOWN = /UNKNOWN|([:.])\w+\1/i; + +var styleSheets = document.styleSheets; + +IE7.CSS = new (Fix.extend({ // single instance + parser: new Parser, + screen: "", + print: "", + styles: [], + rules: [], + pseudoClasses: appVersion < 7 ? "first\\-child" : "", + dynamicPseudoClasses: { + toString: function() { + var strings = []; + for (var pseudoClass in this) strings.push(pseudoClass); + return strings.join("|"); + } + }, + + init: function() { + var NONE = "^\x01$"; + var CLASS = "\\[class=?[^\\]]*\\]"; + var pseudoClasses = []; + if (this.pseudoClasses) pseudoClasses.push(this.pseudoClasses); + var dynamicPseudoClasses = this.dynamicPseudoClasses.toString(); + if (dynamicPseudoClasses) pseudoClasses.push(dynamicPseudoClasses); + pseudoClasses = pseudoClasses.join("|"); + var unknown = appVersion < 7 ? ["[>+~[(]|([:.])\\w+\\1"] : [CLASS]; + if (pseudoClasses) unknown.push(":(" + pseudoClasses + ")"); + this.UNKNOWN = new RegExp(unknown.join("|") || NONE, "i"); + var complex = appVersion < 7 ? ["\\[[^\\]]+\\]|[^\\s(\\[]+\\s*[+~]"] : [CLASS]; + var complexRule = complex.concat(); + if (pseudoClasses) complexRule.push(":(" + pseudoClasses + ")"); + Rule.COMPLEX = new RegExp(complexRule.join("|") || NONE, "ig"); + if (this.pseudoClasses) complex.push(":(" + this.pseudoClasses + ")"); + DynamicRule.COMPLEX = new RegExp(complex.join("|") || NONE, "i"); + DynamicRule.MATCH = new RegExp(dynamicPseudoClasses ? "(.*):(" + dynamicPseudoClasses + ")(.*)" : NONE, "i"); + + this.createStyleSheet(); + this.refresh(); + }, + + addEventHandler: function() { + addEventHandler.apply(null, arguments); + }, + + addFix: function(expression, replacement) { + this.parser.add(expression, replacement); + }, + + addRecalc: function(propertyName, test, handler, replacement) { + // recalcs occur whenever the document is refreshed using document.recalc() + test = new RegExp("([{;\\s])" + propertyName + "\\s*:\\s*" + test + "[^;}]*"); + var id = this.recalcs.length; + if (replacement) replacement = propertyName + ":" + replacement; + this.addFix(test, function(match, $1) { + return (replacement ? $1 + replacement : match) + ";ie7-" + match.slice(1) + ";ie7_recalc" + id + ":1"; + }); + this.recalcs.push(arguments); + return id; + }, + + apply: function() { + this.getInlineStyles(); + new StyleSheet("screen"); + this.trash(); + }, + + createStyleSheet: function() { + // create the IE7 style sheet + this.styleSheet = document.createStyleSheet(); + // flag it so we can ignore it during parsing + this.styleSheet.ie7 = true; + this.styleSheet.owningElement.ie7 = true; + this.styleSheet.cssText = HEADER; + }, + + getInlineStyles: function() { + // load inline styles + var styleSheets = document.getElementsByTagName("style"), styleSheet; + for (var i = styleSheets.length - 1; (styleSheet = styleSheets[i]); i--) { + if (!styleSheet.disabled && !styleSheet.ie7) { + this.styles.push(styleSheet.innerHTML); + } + } + }, + + getText: function(styleSheet, path) { + // explorer will trash unknown selectors (it converts them to "UNKNOWN"). + // so we must reload external style sheets (internal style sheets can have their text + // extracted through the innerHTML property). + // load the style sheet text from an external file + try { + var cssText = styleSheet.cssText; + } catch (e) { + cssText = ""; + } + if (httpRequest) cssText = loadFile(styleSheet.href, path) || cssText; + return cssText; + }, + + recalc: function() { + this.screen.recalc(); + // we're going to read through all style rules. + // certain rules have had ie7 properties added to them. + // e.g. p{top:0; ie7_recalc2:1; left:0} + // this flags a property in the rule as needing a fix. + // the selector text is then used to query the document. + // we can then loop through the results of the query + // and fix the elements. + // we ignore the IE7 rules - so count them in the header + var RECALCS = /ie7_recalc\d+/g; + var start = HEADER.match(/[{,]/g).length; + // only calculate screen fixes. print fixes don't show up anyway + var stop = start + (this.screen.cssText.match(/\{/g)||"").length; + var rules = this.styleSheet.rules, rule; + var calcs, calc, elements, element, i, j, k, id; + // loop through all rules + for (i = start; i < stop; i++) { + rule = rules[i]; + var cssText = rule.style.cssText; + // search for the "ie7_recalc" flag (there may be more than one) + if (rule && (calcs = cssText.match(RECALCS))) { + // use the selector text to query the document + elements = cssQuery(rule.selectorText); + // if there are matching elements then loop + // through the recalc functions and apply them + // to each element + if (elements.length) for (j = 0; j < calcs.length; j++) { + // get the matching flag (e.g. ie7_recalc3) + id = calcs[j]; + // extract the numeric id from the end of the flag + // and use it to index the collection of recalc + // functions + calc = IE7.CSS.recalcs[id.slice(10)][2]; + for (k = 0; (element = elements[k]); k++) { + // apply the fix + if (element.currentStyle[id]) calc(element, cssText); + } + } + } + } + }, + + refresh: function() { + this.styleSheet.cssText = HEADER + this.screen + this.print; + }, + + trash: function() { + // trash the old style sheets + for (var i = 0; i < styleSheets.length; i++) { + if (!styleSheets[i].ie7) { + try { + var cssText = styleSheets[i].cssText; + } catch (e) { + cssText = ""; + } + if (cssText) styleSheets[i].cssText = ""; + } + } + } +})); + +// ----------------------------------------------------------------------- +// IE7 StyleSheet class +// ----------------------------------------------------------------------- + +var StyleSheet = Base.extend({ + constructor: function(media) { + this.media = media; + this.load(); + IE7.CSS[media] = this; + IE7.CSS.refresh(); + }, + + createRule: function(selector, cssText) { + if (IE7.CSS.UNKNOWN.test(selector)) { + var match; + if (PseudoElement && (match = selector.match(PseudoElement.MATCH))) { + return new PseudoElement(match[1], match[2], cssText); + } else if (match = selector.match(DynamicRule.MATCH)) { + if (!HYPERLINK.test(match[0]) || DynamicRule.COMPLEX.test(match[0])) { + return new DynamicRule(selector, match[1], match[2], match[3], cssText); + } + } else return new Rule(selector, cssText); + } + return selector + " {" + cssText + "}"; + }, + + getText: function() { + // store for style sheet text + var _inlineStyles = [].concat(IE7.CSS.styles); + // parse media decalarations + var MEDIA = /@media\s+([^{]*)\{([^@]+\})\s*\}/gi; + var ALL = /\ball\b|^$/i, SCREEN = /\bscreen\b/i, PRINT = /\bprint\b/i; + function _parseMedia(cssText, media) { + _filterMedia.value = media; + return cssText.replace(MEDIA, _filterMedia); + }; + function _filterMedia(match, media, cssText) { + media = _simpleMedia(media); + switch (media) { + case "screen": + case "print": + if (media != _filterMedia.value) return ""; + case "all": + return cssText; + } + return ""; + }; + function _simpleMedia(media) { + if (ALL.test(media)) return "all"; + else if (SCREEN.test(media)) return (PRINT.test(media)) ? "all" : "screen"; + else if (PRINT.test(media)) return "print"; + }; + var self = this; + function _getCSSText(styleSheet, path, media, level) { + var cssText = ""; + if (!level) { + media = _simpleMedia(styleSheet.media); + level = 0; + } + if (media == "all" || media == self.media) { + // IE only allows importing style sheets three levels deep. + // it will crash if you try to access a level below this + if (level < 3) { + // loop through imported style sheets + for (var i = 0; i < styleSheet.imports.length; i++) { + // call this function recursively to get all imported style sheets + cssText += _getCSSText(styleSheet.imports[i], getPath(styleSheet.href, path), media, level + 1); + } + } + // retrieve inline style or load an external style sheet + cssText += encode(styleSheet.href ? _loadStyleSheet(styleSheet, path) : _inlineStyles.pop() || ""); + cssText = _parseMedia(cssText, self.media); + } + return cssText; + }; + // store loaded cssText URLs + var fileCache = {}; + // load an external style sheet + function _loadStyleSheet(styleSheet, path) { + var url = makePath(styleSheet.href, path); + // if the style sheet has already loaded then don't duplicate it + if (fileCache[url]) return ""; + // load from source + fileCache[url] = (styleSheet.disabled) ? "" : + _fixUrls(IE7.CSS.getText(styleSheet, path), getPath(styleSheet.href, path)); + return fileCache[url]; + }; + // fix css paths + // we're lumping all css text into one big style sheet so relative + // paths have to be fixed. this is necessary anyway because of other + // explorer bugs. + var URL = /(url\s*\(\s*['"]?)([\w\.]+[^:\)]*['"]?\))/gi; + function _fixUrls(cssText, pathname) { + // hack & slash + return cssText.replace(URL, "$1" + pathname.slice(0, pathname.lastIndexOf("/") + 1) + "$2"); + }; + + // load all style sheets in the document + for (var i = 0; i < styleSheets.length; i++) { + if (!styleSheets[i].disabled && !styleSheets[i].ie7) { + this.cssText += _getCSSText(styleSheets[i]); + } + } + }, + + load: function() { + this.cssText = ""; + this.getText(); + this.parse(); + this.cssText = decode(this.cssText); + fileCache = {}; + }, + + parse: function() { + this.cssText = IE7.CSS.parser.exec(this.cssText); + + // parse the style sheet + var offset = IE7.CSS.rules.length; + var rules = this.cssText.split(BRACE2), rule; + var selectors, cssText, i, j; + for (i = 0; i < rules.length; i++) { + rule = rules[i].split(BRACE1); + selectors = rule[0].split(COMMA); + cssText = rule[1]; + for (j = 0; j < selectors.length; j++) { + selectors[j] = cssText ? this.createRule(selectors[j], cssText) : ""; + } + rules[i] = selectors.join("\n"); + } + this.cssText = rules.join("\n"); + this.rules = IE7.CSS.rules.slice(offset); + }, + + recalc: function() { + var rule, i; + for (i = 0; (rule = this.rules[i]); i++) rule.recalc(); + }, + + toString: function() { + return "@media " + this.media + "{" + this.cssText + "}"; + } +}); + +var PseudoElement; + +// ----------------------------------------------------------------------- +// IE7 style rules +// ----------------------------------------------------------------------- + +var Rule = IE7.Rule = Base.extend({ + // properties + constructor: function(selector, cssText) { + this.id = IE7.CSS.rules.length; + this.className = Rule.PREFIX + this.id; + selector = selector.match(FIRST_LINE_LETTER) || selector || "*"; + this.selector = selector[1] || selector; + this.selectorText = this.parse(this.selector) + (selector[2] || ""); + this.cssText = cssText; + this.MATCH = new RegExp("\\s" + this.className + "(\\s|$)", "g"); + IE7.CSS.rules.push(this); + this.init(); + }, + + init: Undefined, + + add: function(element) { + // allocate this class + element.className += " " + this.className; + }, + + recalc: function() { + // execute the underlying css query for this class + var match = cssQuery(this.selector); + // add the class name for all matching elements + for (var i = 0; i < match.length; i++) this.add(match[i]); + }, + + parse: function(selector) { + // attempt to preserve specificity for "loose" parsing by + // removing unknown tokens from a css selector but keep as + // much as we can.. + var simple = selector.replace(Rule.CHILD, " ").replace(Rule.COMPLEX, ""); + if (appVersion < 7) simple = simple.replace(Rule.MULTI, ""); + var tags = match(simple, Rule.TAGS).length - match(selector, Rule.TAGS).length; + var classes = match(simple, Rule.CLASSES).length - match(selector, Rule.CLASSES).length + 1; + while (classes > 0 && Rule.CLASS.test(simple)) { + simple = simple.replace(Rule.CLASS, ""); + classes--; + } + while (tags > 0 && Rule.TAG.test(simple)) { + simple = simple.replace(Rule.TAG, "$1*"); + tags--; + } + simple += "." + this.className; + classes = Math.min(classes, 2); + tags = Math.min(tags, 2); + var score = -10 * classes - tags; + if (score > 0) { + simple = simple + "," + Rule.MAP[score] + " " + simple; + } + return simple; + }, + + remove: function(element) { + // deallocate this class + element.className = element.className.replace(this.MATCH, "$1"); + }, + + toString: function() { + return format("%1 {%2}", this.selectorText, this.cssText); + } +}, { + CHILD: />/g, + CLASS: /\.[\w-]+/, + CLASSES: /[.:\[]/g, + MULTI: /(\.[\w-]+)+/g, + PREFIX: "ie7_class", + TAG: /^\w+|([\s>+~])\w+/, + TAGS: /^\w|[\s>+~]\w/g, + MAP: { + 1: "html", + 2: "html body", + 10: ".ie7_html", + 11: "html.ie7_html", + 12: "html.ie7_html body", + 20: ".ie7_html .ie7_body", + 21: "html.ie7_html .ie7_body", + 22: "html.ie7_html body.ie7_body" + } +}); + +// ----------------------------------------------------------------------- +// IE7 dynamic style +// ----------------------------------------------------------------------- + +// object properties: +// attach: the element that an event handler will be attached to +// target: the element that will have the IE7 class applied + +var DynamicRule = Rule.extend({ + // properties + constructor: function(selector, attach, dynamicPseudoClass, target, cssText) { + // initialise object properties + this.attach = attach || "*"; + this.dynamicPseudoClass = IE7.CSS.dynamicPseudoClasses[dynamicPseudoClass]; + this.target = target; + this.base(selector, cssText); + }, + + recalc: function() { + // execute the underlying css query for this class + var attaches = cssQuery(this.attach), attach; + // process results + for (var i = 0; attach = attaches[i]; i++) { + // retrieve the event handler's target element(s) + var target = this.target ? cssQuery(this.target, attach) : [attach]; + // attach event handlers for dynamic pseudo-classes + if (target.length) this.dynamicPseudoClass.apply(attach, target, this); + } + } +}); + +// ----------------------------------------------------------------------- +// IE7 dynamic pseudo-classes +// ----------------------------------------------------------------------- + +var DynamicPseudoClass = Base.extend({ + constructor: function(name, apply) { + this.name = name; + this.apply = apply; + this.instances = {}; + IE7.CSS.dynamicPseudoClasses[name] = this; + }, + + register: function(instance) { + // an "instance" is actually an Arguments object + var _class = instance[2]; + instance.id = _class.id + instance[0].uniqueID; + if (!this.instances[instance.id]) { + var target = instance[1], j; + for (j = 0; j < target.length; j++) _class.add(target[j]); + this.instances[instance.id] = instance; + } + }, + + unregister: function(instance) { + if (this.instances[instance.id]) { + var _class = instance[2]; + var target = instance[1], j; + for (j = 0; j < target.length; j++) _class.remove(target[j]); + delete this.instances[instance.id]; + } + } +}); + +// ----------------------------------------------------------------------- +// dynamic pseudo-classes +// ----------------------------------------------------------------------- + +if (appVersion < 7) { + var Hover = new DynamicPseudoClass("hover", function(element) { + var instance = arguments; + IE7.CSS.addEventHandler(element, appVersion < 5.5 ? "onmouseover" : "onmouseenter", function() { + Hover.register(instance); + }); + IE7.CSS.addEventHandler(element, appVersion < 5.5 ? "onmouseout" : "onmouseleave", function() { + Hover.unregister(instance); + }); + }); + + // globally trap the mouseup event (thanks Martijn!) + addEventHandler(document, "onmouseup", function() { + var instances = Hover.instances; + for (var i in instances) + if (!instances[i][0].contains(event.srcElement)) + Hover.unregister(instances[i]); + }); +} + +// ----------------------------------------------------------------------- +// propertyName: inherit; +// ----------------------------------------------------------------------- + +IE7.CSS.addRecalc("[\\w-]+", "inherit", function(element, cssText) { + var inherited = cssText.match(/[\w-]+\s*:\s*inherit/g); + for (var i = 0; i < inherited.length; i++) { + var propertyName = inherited[i].replace(/ie7\-|\s*:\s*inherit/g, "").replace(/\-([a-z])/g, function(match, chr) { + return chr.toUpperCase() + }); + element.runtimeStyle[propertyName] = element.parentElement.currentStyle[propertyName]; + } +}); + +// ========================================================================= +// ie7-html.js +// ========================================================================= + +// default font-sizes +//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}"; + +IE7.HTML = new (Fix.extend({ // single instance + fixed: {}, + + init: Undefined, + + addFix: function() { + // fixes are a one-off, they are applied when the document is loaded + this.fixes.push(arguments); + }, + + apply: function() { + for (var i = 0; i < this.fixes.length; i++) { + var match = cssQuery(this.fixes[i][0]); + var fix = this.fixes[i][1]; + for (var j = 0; j < match.length; j++) fix(match[j]); + } + }, + + addRecalc: function() { + // recalcs occur whenever the document is refreshed using document.recalc() + this.recalcs.push(arguments); + }, + + recalc: function() { + // loop through the fixes + for (var i = 0; i < this.recalcs.length; i++) { + var match = cssQuery(this.recalcs[i][0]); + var recalc = this.recalcs[i][1], element; + var key = Math.pow(2, i); + for (var j = 0; (element = match[j]); j++) { + var uniqueID = element.uniqueID; + if ((this.fixed[uniqueID] & key) == 0) { + element = recalc(element) || element; + this.fixed[uniqueID] |= key; + } + } + } + } +})); + +if (appVersion < 7) { + // provide support for the tag. + // this is a proper fix, it preserves the DOM structure and + // elements report the correct tagName & namespace prefix + document.createElement("abbr"); + + // bind to the first child control + IE7.HTML.addRecalc("label", function(label) { + if (!label.htmlFor) { + var firstChildControl = cssQuery("input,textarea", label, true); + if (firstChildControl) { + addEventHandler(label, "onclick", function() { + firstChildControl.click(); + }); + } + } + }); +} + +// ========================================================================= +// ie7-layout.js +// ========================================================================= + +var NUMERIC = "[.\\d]"; + +new function(_) { +var layout = IE7.Layout = this; + + // big, ugly box-model hack + min/max stuff + + // #tantek > #erik > #dean { voice-family: hacker; } + + // ----------------------------------------------------------------------- + // "layout" + // ----------------------------------------------------------------------- + + HEADER += "*{boxSizing:content-box}"; + + // does an element have "layout" ? + IE7.hasLayout = appVersion < 5.5 ? function(element) { + // element.currentStyle.hasLayout doesn't work for IE5.0 + return element.clientWidth; + } : function(element) { + return element.currentStyle.hasLayout; + }; + + // give an element "layout" + layout.boxSizing = function(element) { + if (!IE7.hasLayout(element)) { + //# element.runtimeStyle.fixedHeight = + element.style.height = "0cm"; + if (element.currentStyle.verticalAlign == "auto") + element.runtimeStyle.verticalAlign = "top"; + // when an element acquires "layout", margins no longer collapse correctly + collapseMargins(element); + } + }; + + // ----------------------------------------------------------------------- + // Margin Collapse + // ----------------------------------------------------------------------- + + function collapseMargins(element) { + if (element != viewport && element.currentStyle.position != "absolute") { + collapseMargin(element, "marginTop"); + collapseMargin(element, "marginBottom"); + } + }; + + function collapseMargin(element, type) { + if (!element.runtimeStyle[type]) { + var parentElement = element.parentElement; + if (parentElement && IE7.hasLayout(parentElement) && !IE7[type == "marginTop" ? "_getPreviousElementSibling" : "_getNextElementSibling"](element)) return; + var child = cssQuery(">*:" + (type == "marginTop" ? "first" : "last") + "-child", element, true); + if (child && child.currentStyle.styleFloat == "none" && IE7.hasLayout(child)) { + collapseMargin(child, type); + margin = _getMargin(element, element.currentStyle[type]); + childMargin = _getMargin(child, child.currentStyle[type]); + if (margin < 0 || childMargin < 0) { + element.runtimeStyle[type] = margin + childMargin; + } else { + element.runtimeStyle[type] = Math.max(childMargin, margin); + } + child.runtimeStyle[type] = "0px"; + } + } + }; + + function _getMargin(element, value) { + return value == "auto" ? 0 : getPixelValue(element, value); + }; + + // ----------------------------------------------------------------------- + // box-model + // ----------------------------------------------------------------------- + + // constants + var UNIT = /^[.\d][\w%]*$/, AUTO = /^(auto|0cm)$/; + + var applyWidth, applyHeight; + IE7.Layout.borderBox = function(element){ + applyWidth(element); + applyHeight(element); + }; + + var fixWidth = function(HEIGHT) { + applyWidth = function(element) { + if (!PERCENT.test(element.currentStyle.width)) fixWidth(element); + collapseMargins(element); + }; + + function fixWidth(element, value) { + if (!element.runtimeStyle.fixedWidth) { + if (!value) value = element.currentStyle.width; + element.runtimeStyle.fixedWidth = (UNIT.test(value)) ? Math.max(0, getFixedWidth(element, value)) : value; + setOverrideStyle(element, "width", element.runtimeStyle.fixedWidth); + } + }; + + function layoutWidth(element) { + if (!isFixed(element)) { + var layoutParent = element.offsetParent; + while (layoutParent && !IE7.hasLayout(layoutParent)) layoutParent = layoutParent.offsetParent; + } + return (layoutParent || viewport).clientWidth; + }; + + function getPixelWidth(element, value) { + if (PERCENT.test(value)) return parseInt(parseFloat(value) / 100 * layoutWidth(element)); + return getPixelValue(element, value); + }; + + var getFixedWidth = function(element, value) { + var borderBox = element.currentStyle["box-sizing"] == "border-box"; + var adjustment = 0; + if (quirksMode && !borderBox) + adjustment += getBorderWidth(element) + getWidth(element, "padding"); + else if (!quirksMode && borderBox) + adjustment -= getBorderWidth(element) + getWidth(element, "padding"); + return getPixelWidth(element, value) + adjustment; + }; + + // easy way to get border thickness for elements with "layout" + function getBorderWidth(element) { + return element.offsetWidth - element.clientWidth; + }; + + // have to do some pixel conversion to get padding/margin thickness :-( + function getWidth(element, type) { + return getPixelWidth(element, element.currentStyle[type + "Left"]) + getPixelWidth(element, element.currentStyle[type + "Right"]); + }; + + // ----------------------------------------------------------------------- + // min/max + // ----------------------------------------------------------------------- + + HEADER += "*{minWidth:none;maxWidth:none;min-width:none;max-width:none}"; + + // handle min-width property + layout.minWidth = function(element) { + // IE6 supports min-height so we frig it here + //#if (element.currentStyle.minHeight == "auto") element.runtimeStyle.minHeight = 0; + if (element.currentStyle["min-width"] != null) { + element.style.minWidth = element.currentStyle["min-width"]; + } + if (register(arguments.callee, element, element.currentStyle.minWidth != "none")) { + layout.boxSizing(element); + fixWidth(element); + resizeWidth(element); + } + }; + + // clone the minWidth function to make a maxWidth function + eval("IE7.Layout.maxWidth=" + String(layout.minWidth).replace(/min/g, "max")); + + // apply min/max restrictions + function resizeWidth(element) { + // check boundaries + var rect = element.getBoundingClientRect(); + var width = rect.right - rect.left; + + if (element.currentStyle.minWidth != "none" && width <= getFixedWidth(element, element.currentStyle.minWidth)) { + element.runtimeStyle.width = element.currentStyle.minWidth; + } else if (element.currentStyle.maxWidth != "none" && width >= getFixedWidth(element, element.currentStyle.maxWidth)) { + element.runtimeStyle.width = element.currentStyle.maxWidth; + } else { + element.runtimeStyle.width = element.runtimeStyle.fixedWidth; // || "auto"; + } + }; + + // ----------------------------------------------------------------------- + // right/bottom + // ----------------------------------------------------------------------- + + function fixRight(element) { + if (register(fixRight, element, /^(fixed|absolute)$/.test(element.currentStyle.position) && + getDefinedStyle(element, "left") != "auto" && + getDefinedStyle(element, "right") != "auto" && + AUTO.test(getDefinedStyle(element, "width")))) { + resizeRight(element); + IE7.Layout.boxSizing(element); + } + }; + IE7.Layout.fixRight = fixRight; + + function resizeRight(element) { + var left = getPixelWidth(element, element.runtimeStyle._left || element.currentStyle.left); + var width = layoutWidth(element) - getPixelWidth(element, element.currentStyle.right) - left - getWidth(element, "margin"); + if (parseInt(element.runtimeStyle.width) == width) return; + element.runtimeStyle.width = ""; + if (isFixed(element) || HEIGHT || element.offsetWidth < width) { + if (!quirksMode) width -= getBorderWidth(element) + getWidth(element, "padding"); + if (width < 0) width = 0; + element.runtimeStyle.fixedWidth = width; + setOverrideStyle(element, "width", width); + } + }; + + // ----------------------------------------------------------------------- + // window.onresize + // ----------------------------------------------------------------------- + + // handle window resize + var clientWidth = 0; + addResize(function() { + if (!viewport) return; + var i, wider = (clientWidth < viewport.clientWidth); + clientWidth = viewport.clientWidth; + // resize elements with "min-width" set + var elements = layout.minWidth.elements; + for (i in elements) { + var element = elements[i]; + var fixedWidth = (parseInt(element.runtimeStyle.width) == getFixedWidth(element, element.currentStyle.minWidth)); + if (wider && fixedWidth) element.runtimeStyle.width = ""; + if (wider == fixedWidth) resizeWidth(element); + } + // resize elements with "max-width" set + var elements = layout.maxWidth.elements; + for (i in elements) { + var element = elements[i]; + var fixedWidth = (parseInt(element.runtimeStyle.width) == getFixedWidth(element, element.currentStyle.maxWidth)); + if (!wider && fixedWidth) element.runtimeStyle.width = ""; + if (wider != fixedWidth) resizeWidth(element); + } + // resize elements with "right" set + for (i in fixRight.elements) resizeRight(fixRight.elements[i]); + }); + + // ----------------------------------------------------------------------- + // fix CSS + // ----------------------------------------------------------------------- + if (quirksMode) { + IE7.CSS.addRecalc("width", NUMERIC, applyWidth); + } + if (appVersion < 7) { + IE7.CSS.addRecalc("min-width", NUMERIC, layout.minWidth); + IE7.CSS.addRecalc("max-width", NUMERIC, layout.maxWidth); + IE7.CSS.addRecalc("right", NUMERIC, fixRight); + } + }; + + eval("var fixHeight=" + rotate(fixWidth)); + + // apply box-model + min/max fixes + fixWidth(); + fixHeight(true); +}; + +// ========================================================================= +// ie7-graphics.js +// ========================================================================= + +// a small transparent image used as a placeholder +var BLANK_GIF = makePath("blank.gif", path); + +var ALPHA_IMAGE_LOADER = "DXImageTransform.Microsoft.AlphaImageLoader"; +var PNG_FILTER = "progid:" + ALPHA_IMAGE_LOADER + "(src='%1',sizingMethod='%2')"; + +// regular expression version of the above +var PNG; + +var filtered = []; + +function fixImage(element) { + if (PNG.test(element.src)) { + // we have to preserve width and height + var image = new Image(element.width, element.height); + image.onload = function() { + element.width = image.width; + element.height = image.height; + image = null; + }; + image.src = element.src; + // store the original url (we'll put it back when it's printed) + element.pngSrc = element.src; + // add the AlphaImageLoader thingy + addFilter(element); + } +}; + +if (appVersion >= 5.5 && appVersion < 7) { + // ** IE7 VARIABLE + // e.g. only apply the hack to files ending in ".png" + // IE7_PNG_SUFFIX = ".png"; + + // replace background(-image): url(..) .. with background(-image): .. ;filter: ..; + IE7.CSS.addFix(/background(-image)?\s*:\s*([^};]*)?url\(([^\)]+)\)([^;}]*)?/, function(match, $1, $2, url, $4) { + url = getString(url); + return PNG.test(url) ? "filter:" + format(PNG_FILTER, url, "crop") + + ";zoom:1;background" + ($1||"") + ":" + ($2||"") + "none" + ($4||"") : match; + }); + + // ----------------------------------------------------------------------- + // fix PNG transparency (HTML images) + // ----------------------------------------------------------------------- + + IE7.HTML.addRecalc("img,input", function(element) { + if (element.tagName == "INPUT" && element.type != "image") return; + fixImage(element); + addEventHandler(element, "onpropertychange", function() { + if (!printing && event.propertyName == "src" && + element.src.indexOf(BLANK_GIF) == -1) fixImage(element); + }); + }); + + // assume that background images should not be printed + // (if they are not transparent then they'll just obscure content) + // but we'll put foreground images back... + var printing = false; + addEventHandler(window, "onbeforeprint", function() { + printing = true; + for (var i = 0; i < filtered.length; i++) removeFilter(filtered[i]); + }); + addEventHandler(window, "onafterprint", function() { + for (var i = 0; i < filtered.length; i++) addFilter(filtered[i]); + printing = false; + }); +} + +// apply a filter +function addFilter(element, sizingMethod) { + var filter = element.filters[ALPHA_IMAGE_LOADER]; + if (filter) { + filter.src = element.src; + filter.enabled = true; + } else { + element.runtimeStyle.filter = format(PNG_FILTER, element.src, sizingMethod || "scale"); + filtered.push(element); + } + // remove the real image + element.src = BLANK_GIF; +}; + +function removeFilter(element) { + element.src = element.pngSrc; + element.filters[ALPHA_IMAGE_LOADER].enabled = false; +}; + +// ========================================================================= +// ie7-fixed.js +// ========================================================================= + +new function(_) { + if (appVersion >= 7) return; + + // some things to consider for this hack. + // the document body requires a fixed background. even if + // it is just a blank image. + // you have to use setExpression instead of onscroll, this + // together with a fixed body background helps avoid the + // annoying screen flicker of other solutions. + + IE7.CSS.addRecalc("position", "fixed", _positionFixed, "absolute"); + IE7.CSS.addRecalc("background(-attachment)?", "[^};]*fixed", _backgroundFixed); + + // scrolling is relative to the documentElement (HTML tag) when in + // standards mode, otherwise it's relative to the document body + var $viewport = quirksMode ? "body" : "documentElement"; + + function _fixBackground() { + // this is required by both position:fixed and background-attachment:fixed. + // it is necessary for the document to also have a fixed background image. + // we can fake this with a blank image if necessary + if (body.currentStyle.backgroundAttachment != "fixed") { + if (body.currentStyle.backgroundImage == "none") { + body.runtimeStyle.backgroundRepeat = "no-repeat"; + body.runtimeStyle.backgroundImage = "url(" + BLANK_GIF + ")"; // dummy + } + body.runtimeStyle.backgroundAttachment = "fixed"; + } + _fixBackground = Undefined; + }; + + var _tmp = createTempElement("img"); + + function _isFixed(element) { + return element ? isFixed(element) || _isFixed(element.parentElement) : false; + }; + + function _setExpression(element, propertyName, expression) { + setTimeout("document.all." + element.uniqueID + ".runtimeStyle.setExpression('" + propertyName + "','" + expression + "')", 0); + }; + + // ----------------------------------------------------------------------- + // backgroundAttachment: fixed + // ----------------------------------------------------------------------- + + function _backgroundFixed(element) { + if (register(_backgroundFixed, element, element.currentStyle.backgroundAttachment == "fixed" && !element.contains(body))) { + _fixBackground(); + bgLeft(element); + bgTop(element); + _backgroundPosition(element); + } + }; + + function _backgroundPosition(element) { + _tmp.src = element.currentStyle.backgroundImage.slice(5, -2); + var parentElement = element.canHaveChildren ? element : element.parentElement; + parentElement.appendChild(_tmp); + setOffsetLeft(element); + setOffsetTop(element); + parentElement.removeChild(_tmp); + }; + + function bgLeft(element) { + element.style.backgroundPositionX = element.currentStyle.backgroundPositionX; + if (!_isFixed(element)) { + _setExpression(element, "backgroundPositionX", "(parseInt(runtimeStyle.offsetLeft)+document." + $viewport + ".scrollLeft)||0"); + } + }; + eval(rotate(bgLeft)); + + function setOffsetLeft(element) { + var propertyName = _isFixed(element) ? "backgroundPositionX" : "offsetLeft"; + element.runtimeStyle[propertyName] = + getOffsetLeft(element, element.style.backgroundPositionX) - + element.getBoundingClientRect().left - element.clientLeft + 2; + }; + eval(rotate(setOffsetLeft)); + + function getOffsetLeft(element, position) { + switch (position) { + case "left": + case "top": + return 0; + case "right": + case "bottom": + return viewport.clientWidth - _tmp.offsetWidth; + case "center": + return (viewport.clientWidth - _tmp.offsetWidth) / 2; + default: + if (PERCENT.test(position)) { + return parseInt((viewport.clientWidth - _tmp.offsetWidth) * parseFloat(position) / 100); + } + _tmp.style.left = position; + return _tmp.offsetLeft; + } + }; + eval(rotate(getOffsetLeft)); + + // ----------------------------------------------------------------------- + // position: fixed + // ----------------------------------------------------------------------- + + function _positionFixed(element) { + if (register(_positionFixed, element, isFixed(element))) { + setOverrideStyle(element, "position", "absolute"); + setOverrideStyle(element, "left", element.currentStyle.left); + setOverrideStyle(element, "top", element.currentStyle.top); + _fixBackground(); + IE7.Layout.fixRight(element); + _foregroundPosition(element); + } + }; + + function _foregroundPosition(element, recalc) { + positionTop(element, recalc); + positionLeft(element, recalc, true); + if (!element.runtimeStyle.autoLeft && element.currentStyle.marginLeft == "auto" && + element.currentStyle.right != "auto") { + var left = viewport.clientWidth - getPixelWidth(element, element.currentStyle.right) - + getPixelWidth(element, element.runtimeStyle._left) - element.clientWidth; + if (element.currentStyle.marginRight == "auto") left = parseInt(left / 2); + if (_isFixed(element.offsetParent)) element.runtimeStyle.pixelLeft += left; + else element.runtimeStyle.shiftLeft = left; + } + clipWidth(element); + clipHeight(element); + }; + + function clipWidth(element) { + var fixWidth = element.runtimeStyle.fixWidth; + element.runtimeStyle.borderRightWidth = ""; + element.runtimeStyle.width = fixWidth ? getPixelWidth(element, fixWidth) : ""; + if (element.currentStyle.width != "auto") { + var rect = element.getBoundingClientRect(); + var width = element.offsetWidth - viewport.clientWidth + rect.left - 2; + if (width >= 0) { + element.runtimeStyle.borderRightWidth = "0px"; + width = Math.max(getPixelValue(element, element.currentStyle.width) - width, 0); + setOverrideStyle(element, "width", width); + return width; + } + } + }; + eval(rotate(clipWidth)); + + function positionLeft(element, recalc) { + // if the element's width is in % units then it must be recalculated + // with respect to the viewport + if (!recalc && PERCENT.test(element.currentStyle.width)) { + element.runtimeStyle.fixWidth = element.currentStyle.width; + } + if (element.runtimeStyle.fixWidth) { + element.runtimeStyle.width = getPixelWidth(element, element.runtimeStyle.fixWidth); + } + //if (recalc) { + // // if the element is fixed on the right then no need to recalculate + // if (!element.runtimeStyle.autoLeft) return; + //} else { + element.runtimeStyle.shiftLeft = 0; + element.runtimeStyle._left = element.currentStyle.left; + // is the element fixed on the right? + element.runtimeStyle.autoLeft = element.currentStyle.right != "auto" && + element.currentStyle.left == "auto"; + //} + // reset the element's "left" value and get it's natural position + element.runtimeStyle.left = ""; + element.runtimeStyle.screenLeft = getScreenLeft(element); + element.runtimeStyle.pixelLeft = element.runtimeStyle.screenLeft; + // if the element is contained by another fixed element then there is no need to + // continually recalculate it's left position + if (!recalc && !_isFixed(element.offsetParent)) { + // onsrcoll produces jerky movement, so we use an expression + _setExpression(element, "pixelLeft", "runtimeStyle.screenLeft+runtimeStyle.shiftLeft+document." + $viewport + ".scrollLeft"); + } + }; + // clone this function so we can do "top" + eval(rotate(positionLeft)); + + // I've forgotten how this works... + function getScreenLeft(element) { // thanks to kevin newman (captainn) + var screenLeft = element.offsetLeft, nested = 1; + if (element.runtimeStyle.autoLeft) { + screenLeft = viewport.clientWidth - element.offsetWidth - getPixelWidth(element, element.currentStyle.right); + } + // accommodate margins + if (element.currentStyle.marginLeft != "auto") { + screenLeft -= getPixelWidth(element, element.currentStyle.marginLeft); + } + while (element = element.offsetParent) { + if (element.currentStyle.position != "static") nested = -1; + screenLeft += element.offsetLeft * nested; + } + return screenLeft; + }; + eval(rotate(getScreenLeft)); + + function getPixelWidth(element, value) { + return PERCENT.test(value) ? parseInt(parseFloat(value) / 100 * viewport.clientWidth) : getPixelValue(element, value); + }; + eval(rotate(getPixelWidth)); + + // ----------------------------------------------------------------------- + // capture window resize + // ----------------------------------------------------------------------- + + function _resize() { + // if the window has been resized then some positions need to be + // recalculated (especially those aligned to "right" or "top" + var elements = _backgroundFixed.elements; + for (var i in elements) _backgroundPosition(elements[i]); + elements = _positionFixed.elements; + for (i in elements) { + _foregroundPosition(elements[i], true); + // do this twice to be sure - hackish, I know :-) + _foregroundPosition(elements[i], true); + } + _timer = 0; + }; + + // use a timer for some reason. + // (sometimes this is a good way to prevent resize loops) + var _timer; + addResize(function() { + if (!_timer) _timer = setTimeout(_resize, 0); + }); +}; + +// ========================================================================= +// ie7-oveflow.js +// ========================================================================= + +/* --------------------------------------------------------------------- + + This module alters the structure of the document. + It may adversely affect other CSS rules. Be warned. + +--------------------------------------------------------------------- */ + +var WRAPPER_STYLE = { + backgroundColor: "transparent", + backgroundImage: "none", + backgroundPositionX: null, + backgroundPositionY: null, + backgroundRepeat: null, + borderTopWidth: 0, + borderRightWidth: 0, + borderBottomWidth: 0, + borderLeftStyle: "none", + borderTopStyle: "none", + borderRightStyle: "none", + borderBottomStyle: "none", + borderLeftWidth: 0, + height: null, + marginTop: 0, + marginBottom: 0, + marginRight: 0, + marginLeft: 0, + width: "100%" +}; + +IE7.CSS.addRecalc("overflow", "visible", function(element) { + // don't do this again + if (element.parentNode.ie7_wrapped) return; + + // if max-height is applied, makes sure it gets applied first + if (IE7.Layout && element.currentStyle["max-height"] != "auto") { + IE7.Layout.maxHeight(element); + } + + if (element.currentStyle.marginLeft == "auto") element.style.marginLeft = 0; + if (element.currentStyle.marginRight == "auto") element.style.marginRight = 0; + + var wrapper = document.createElement(ANON); + wrapper.ie7_wrapped = element; + for (var propertyName in WRAPPER_STYLE) { + wrapper.style[propertyName] = element.currentStyle[propertyName]; + if (WRAPPER_STYLE[propertyName] != null) { + element.runtimeStyle[propertyName] = WRAPPER_STYLE[propertyName]; + } + } + wrapper.style.display = "block"; + wrapper.style.position = "relative"; + element.runtimeStyle.position = "absolute"; + element.parentNode.insertBefore(wrapper, element); + wrapper.appendChild(element); +}); + +// ========================================================================= +// ie7-quirks.js +// ========================================================================= + +function ie7Quirks() { + var FONT_SIZES = "xx-small,x-small,small,medium,large,x-large,xx-large".split(","); + for (var i = 0; i < FONT_SIZES.length; i++) { + FONT_SIZES[FONT_SIZES[i]] = FONT_SIZES[i - 1] || "0.67em"; + } + + IE7.CSS.addFix(/(font(-size)?\s*:\s*)([\w.-]+)/, function(match, label, size, value) { + return label + (FONT_SIZES[value] || value); + }); + + if (appVersion < 6) { + var NEGATIVE = /^\-/, LENGTH = /(em|ex)$/i; + var EM = /em$/i, EX = /ex$/i; + + getPixelValue = function(element, value) { + if (PIXEL.test(value)) return parseInt(value)||0; + var scale = NEGATIVE.test(value)? -1 : 1; + if (LENGTH.test(value)) scale *= getFontScale(element); + temp.style.width = (scale < 0) ? value.slice(1) : value; + body.appendChild(temp); + // retrieve pixel width + value = scale * temp.offsetWidth; + // remove the temporary element + temp.removeNode(); + return parseInt(value); + }; + + var temp = createTempElement(); + function getFontScale(element) { + var scale = 1; + temp.style.fontFamily = element.currentStyle.fontFamily; + temp.style.lineHeight = element.currentStyle.lineHeight; + //temp.style.fontSize = ""; + while (element != body) { + var fontSize = element.currentStyle["ie7-font-size"]; + if (fontSize) { + if (EM.test(fontSize)) scale *= parseFloat(fontSize); + else if (PERCENT.test(fontSize)) scale *= (parseFloat(fontSize) / 100); + else if (EX.test(fontSize)) scale *= (parseFloat(fontSize) / 2); + else { + temp.style.fontSize = fontSize; + return 1; + } + } + element = element.parentElement; + } + return scale; + }; + + // cursor:pointer (IE5.x) + IE7.CSS.addFix(/cursor\s*:\s*pointer/, "cursor:hand"); + // display:list-item (IE5.x) + IE7.CSS.addFix(/display\s*:\s*list-item/, "display:block"); + } + + // ----------------------------------------------------------------------- + // margin:auto + // ----------------------------------------------------------------------- + + function fixMargin(element) { + if (appVersion < 5.5) IE7.Layout.boxSizing(element.parentElement); + var parent = element.parentElement; + var margin = parent.offsetWidth - element.offsetWidth - getPaddingWidth(parent); + var autoRight = (element.currentStyle["ie7-margin"] && element.currentStyle.marginRight == "auto") || + element.currentStyle["ie7-margin-right"] == "auto"; + switch (parent.currentStyle.textAlign) { + case "right": + margin = autoRight ? parseInt(margin / 2) : 0; + element.runtimeStyle.marginRight = margin + "px"; + break; + case "center": + if (autoRight) margin = 0; + default: + if (autoRight) margin /= 2; + element.runtimeStyle.marginLeft = parseInt(margin) + "px"; + } + }; + + function getPaddingWidth(element) { + return getPixelValue(element, element.currentStyle.paddingLeft) + + getPixelValue(element, element.currentStyle.paddingRight); + }; + + IE7.CSS.addRecalc("margin(-left|-right)?", "[^};]*auto", function(element) { + if (register(fixMargin, element, + element.parentElement && + element.currentStyle.display == "block" && + element.currentStyle.marginLeft == "auto" && + element.currentStyle.position != "absolute")) { + fixMargin(element); + } + }); + + addResize(function() { + for (var i in fixMargin.elements) { + var element = fixMargin.elements[i]; + element.runtimeStyle.marginLeft = + element.runtimeStyle.marginRight = ""; + fixMargin(element); + } + }); +}; + + +// ========================================================================= +// ie8-cssQuery.js +// ========================================================================= + +IE7._isEmpty = function(element) { + element = element.firstChild; + while (element) { + if (element.nodeType == 3 || (element.nodeType == 1 && element.nodeName != "!")) return false; + element = element.nextSibling; + } + return true; +}; + +IE7._isLang = function(element, code) { + while (element && !element.getAttribute("lang")) element = element.parentNode; + return element && new RegExp("^" + rescape(code), "i").test(element.getAttribute("lang")); +}; + +function _nthChild(match, args, position, last) { + // ugly but it works... + last = /last/i.test(match) ? last + "+1-" : ""; + if (!isNaN(args)) args = "0n+" + args; + else if (args == "even") args = "2n"; + else if (args == "odd") args = "2n+1"; + args = args.split("n"); + var a = args[0] ? (args[0] == "-") ? -1 : parseInt(args[0]) : 1; + var b = parseInt(args[1]) || 0; + var negate = a < 0; + if (negate) { + a = -a; + if (a == 1) b++; + } + var query = format(a == 0 ? "%3%7" + (last + b) : "(%4%3-%2)%6%1%70%5%4%3>=%2", a, b, position, last, "&&", "%", "=="); + if (negate) query = "!(" + query + ")"; + return query; +}; + +_PSEUDO_CLASSES = { + "link": "e%1.currentStyle['ie7-link']=='link'", + "visited": "e%1.currentStyle['ie7-link']=='visited'", + "checked": "e%1.checked", + "contains": "e%1.innerText.indexOf('%2')!=-1", + "disabled": "e%1.isDisabled", + "empty": "IE7._isEmpty(e%1)", + "enabled": "e%1.disabled===false", + "first-child": "!IE7._getPreviousElementSibling(e%1)", + "lang": "IE7._isLang(e%1,'%2')", + "last-child": "!IE7._getNextElementSibling(e%1)", + "only-child": "!IE7._getPreviousElementSibling(e%1)&&!IE7._getNextElementSibling(e%1)", + "target": "e%1.id==location.hash.slice(1)", + "indeterminate": "e%1.indeterminate" +}; + + +// register a node and index its children +IE7._register = function(element) { + if (element.rows) { + element.ie7_length = element.rows.length; + element.ie7_lookup = "rowIndex"; + } else if (element.cells) { + element.ie7_length = element.cells.length; + element.ie7_lookup = "cellIndex"; + } else if (element.ie7_indexed != IE7._indexed) { + var index = 0; + var child = element.firstChild; + while (child) { + if (child.nodeType == 1 && child.nodeName != "!") { + child.ie7_index = ++index; + } + child = child.nextSibling; + } + element.ie7_length = index; + element.ie7_lookup = "ie7_index"; + } + element.ie7_indexed = IE7._indexed; + return element; +}; + +var keys = cssParser[_KEYS]; +var pseudoClass = keys[keys.length - 1]; +keys.length--; + +cssParser.merge({ + ":not\\((\\*|[\\w-]+)?([^)]*)\\)": function(match, tagName, filters) { // :not pseudo class + var replacement = (tagName && tagName != "*") ? format("if(e%1.nodeName=='%2'){", _index, tagName.toUpperCase()) : ""; + replacement += cssParser.exec(filters); + return "if(!" + replacement.slice(2, -1).replace(/\)\{if\(/g, "&&") + "){"; + }, + + ":nth(-last)?-child\\(([^)]+)\\)": function(match, last, args) { // :nth-child pseudo classes + _wild = false; + last = format("e%1.parentNode.ie7_length", _index); + var replacement = "if(p%1!==e%1.parentNode)p%1=IE7._register(e%1.parentNode);"; + replacement += "var i=e%1[p%1.ie7_lookup];if(p%1.ie7_lookup!='ie7_index')i++;if("; + return format(replacement, _index) + _nthChild(match, args, "i", last) + "){"; + } +}); + +keys.push(pseudoClass); + +// ========================================================================= +// ie8-css.js +// ========================================================================= + +var BRACKETS = "\\([^)]*\\)"; + +if (IE7.CSS.pseudoClasses) IE7.CSS.pseudoClasses += "|"; +IE7.CSS.pseudoClasses += "before|after|last\\-child|only\\-child|empty|root|" + + "not|nth\\-child|nth\\-last\\-child|contains|lang".split("|").join(BRACKETS + "|") + BRACKETS; + +// pseudo-elements can be declared with a double colon +encoder.add(/::/, ":"); + +// ----------------------------------------------------------------------- +// dynamic pseudo-classes +// ----------------------------------------------------------------------- + +var Focus = new DynamicPseudoClass("focus", function(element) { + var instance = arguments; + + IE7.CSS.addEventHandler(element, "onfocus", function() { + Focus.unregister(instance); // in case it starts with focus + Focus.register(instance); + }); + + IE7.CSS.addEventHandler(element, "onblur", function() { + Focus.unregister(instance); + }); + + // check the active element for initial state + if (element == document.activeElement) { + Focus.register(instance) + } +}); + +var Active = new DynamicPseudoClass("active", function(element) { + var instance = arguments; + IE7.CSS.addEventHandler(element, "onmousedown", function() { + Active.register(instance); + }); +}); + +// globally trap the mouseup event (thanks Martijn!) +addEventHandler(document, "onmouseup", function() { + var instances = Active.instances; + for (var i in instances) Active.unregister(instances[i]); +}); + +// :checked +var Checked = new DynamicPseudoClass("checked", function(element) { + if (typeof element.checked != "boolean") return; + var instance = arguments; + IE7.CSS.addEventHandler(element, "onpropertychange", function() { + if (event.propertyName == "checked") { + if (element.checked) Checked.register(instance); + else Checked.unregister(instance); + } + }); + // check current checked state + if (element.checked) Checked.register(instance); +}); + +// :enabled +var Enabled = new DynamicPseudoClass("enabled", function(element) { + if (typeof element.disabled != "boolean") return; + var instance = arguments; + IE7.CSS.addEventHandler(element, "onpropertychange", function() { + if (event.propertyName == "disabled") { + if (!element.isDisabled) Enabled.register(instance); + else Enabled.unregister(instance); + } + }); + // check current disabled state + if (!element.isDisabled) Enabled.register(instance); +}); + +// :disabled +var Disabled = new DynamicPseudoClass("disabled", function(element) { + if (typeof element.disabled != "boolean") return; + var instance = arguments; + IE7.CSS.addEventHandler(element, "onpropertychange", function() { + if (event.propertyName == "disabled") { + if (element.isDisabled) Disabled.register(instance); + else Disabled.unregister(instance); + } + }); + // check current disabled state + if (element.isDisabled) Disabled.register(instance); +}); + +// :indeterminate (Kevin Newman) +var Indeterminate = new DynamicPseudoClass("indeterminate", function(element) { + if (typeof element.indeterminate != "boolean") return; + var instance = arguments; + IE7.CSS.addEventHandler(element, "onpropertychange", function() { + if (event.propertyName == "indeterminate") { + if (element.indeterminate) Indeterminate.register(instance); + else Indeterminate.unregister(instance); + } + }); + IE7.CSS.addEventHandler(element, "onclick", function() { + Indeterminate.unregister(instance); + }); + // clever Kev says no need to check this up front +}); + +// :target +var Target = new DynamicPseudoClass("target", function(element) { + var instance = arguments; + // if an element has a tabIndex then it can become "active". + // The default is zero anyway but it works... + if (!element.tabIndex) element.tabIndex = 0; + // this doesn't detect the back button. I don't know how to do that :-( + IE7.CSS.addEventHandler(document, "onpropertychange", function() { + if (event.propertyName == "activeElement") { + if (element.id && element.id == location.hash.slice(1)) Target.register(instance); + else Target.unregister(instance); + } + }); + // check the current location + if (element.id && element.id == location.hash.slice(1)) Target.register(instance); +}); + +// ----------------------------------------------------------------------- +// IE7 pseudo elements +// ----------------------------------------------------------------------- + +// constants +var ATTR = /^attr/; +var URL = /^url\s*\(\s*([^)]*)\)$/; +var POSITION_MAP = { + before0: "beforeBegin", + before1: "afterBegin", + after0: "afterEnd", + after1: "beforeEnd" +}; + +var PseudoElement = IE7.PseudoElement = Rule.extend({ + constructor: function(selector, position, cssText) { + // initialise object properties + this.position = position; + var content = cssText.match(PseudoElement.CONTENT), match, entity; + if (content) { + content = content[1]; + match = content.split(/\s+/); + for (var i = 0; (entity = match[i]); i++) { + match[i] = ATTR.test(entity) ? {attr: entity.slice(5, -1)} : + (entity.charAt(0) == "'") ? getString(entity) : decode(entity); + } + content = match; + } + this.content = content; + // CSS text needs to be decoded immediately + this.base(selector, decode(cssText)); + }, + + init: function() { + // execute the underlying css query for this class + this.match = cssQuery(this.selector); + for (var i = 0; i < this.match.length; i++) { + var runtimeStyle = this.match[i].runtimeStyle; + if (!runtimeStyle[this.position]) runtimeStyle[this.position] = {cssText:""}; + runtimeStyle[this.position].cssText += ";" + this.cssText; + if (this.content != null) runtimeStyle[this.position].content = this.content; + } + }, + + create: function(target) { + var generated = target.runtimeStyle[this.position]; + if (generated) { + // copy the array of values + var content = [].concat(generated.content || ""); + for (var j = 0; j < content.length; j++) { + if (typeof content[j] == "object") { + content[j] = target.getAttribute(content[j].attr); + } + } + content = content.join(""); + var url = content.match(URL); + var cssText = "overflow:hidden;" + generated.cssText.replace(/'/g, '"'); + if (target.currentStyle.styleFloat != "none") { + //cssText = cssText.replace(/display\s*:\s*block/, "display:inline-block"); + } + var position = POSITION_MAP[this.position + Number(target.canHaveChildren)]; + var id = 'ie7_pseudo' + PseudoElement.count++; + target.insertAdjacentHTML(position, format(PseudoElement.ANON, this.className, id, cssText, url ? "" : content)); + if (url) { + var pseudoElement = document.getElementById(id); + pseudoElement.src = getString(url[1]); + addFilter(pseudoElement, "crop"); + } + target.runtimeStyle[this.position] = null; + } + }, + + recalc: function() { + if (this.content == null) return; + for (var i = 0; i < this.match.length; i++) { + this.create(this.match[i]); + } + }, + + toString: function() { + return "." + this.className + "{display:inline}"; + } +}, { + CONTENT: /content\s*:\s*([^;]*)(;|$)/, + ANON: "%4", + MATCH: /(.*):(before|after).*/, + + count: 0 +}); + +// ========================================================================= +// ie8-html.js +// ========================================================================= + +var UNSUCCESSFUL = /^(submit|reset|button)$/; + +// ----------------------------------------------------------------------- +//