mirror of
https://github.com/galaxyproject/galaxy.git
synced 2026-09-22 06:16:50 +08:00
every page can be added to galaxy.base.js). Cleaned up history templates accordingly. Also, added scripts from IE7.js which fix many layout bugs in older versions of IE.
2602 lines
88 KiB
JavaScript
2602 lines
88 KiB
JavaScript
// 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 <abbr> tag.
|
|
// this is a proper fix, it preserves the DOM structure and
|
|
// <abbr> 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: "<ie7:! class='ie7_anon %1' id=%2 style='%3'>%4</ie7:!>",
|
|
MATCH: /(.*):(before|after).*/,
|
|
|
|
count: 0
|
|
});
|
|
|
|
// =========================================================================
|
|
// ie8-html.js
|
|
// =========================================================================
|
|
|
|
var UNSUCCESSFUL = /^(submit|reset|button)$/;
|
|
|
|
// -----------------------------------------------------------------------
|
|
// <button>
|
|
// -----------------------------------------------------------------------
|
|
|
|
// IE bug means that innerText is submitted instead of "value"
|
|
IE7.HTML.addRecalc("button,input", function(button) {
|
|
if (button.tagName == "BUTTON") {
|
|
var match = button.outerHTML.match(/ value="([^"]*)"/i);
|
|
button.runtimeStyle.value = (match) ? match[1] : "";
|
|
}
|
|
// flag the button/input that was used to submit the form
|
|
if (button.type == "submit") {
|
|
addEventHandler(button, "onclick", function() {
|
|
button.runtimeStyle.clicked = true;
|
|
setTimeout("document.all." + button.uniqueID + ".runtimeStyle.clicked=false", 1);
|
|
});
|
|
}
|
|
});
|
|
|
|
// -----------------------------------------------------------------------
|
|
// <form>
|
|
// -----------------------------------------------------------------------
|
|
|
|
// only submit "successful controls
|
|
IE7.HTML.addRecalc("form", function(form) {
|
|
addEventHandler(form, "onsubmit", function() {
|
|
for (var element, i = 0; element = form[i]; i++) {
|
|
if (UNSUCCESSFUL.test(element.type) && !element.disabled && !element.runtimeStyle.clicked) {
|
|
element.disabled = true;
|
|
setTimeout("document.all." + element.uniqueID + ".disabled=false", 1);
|
|
} else if (element.tagName == "BUTTON" && element.type == "submit") {
|
|
setTimeout("document.all." + element.uniqueID + ".value='" +
|
|
element.value + "'", 1);
|
|
element.value = element.runtimeStyle.value;
|
|
}
|
|
}
|
|
});
|
|
});
|
|
|
|
// -----------------------------------------------------------------------
|
|
// <img>
|
|
// -----------------------------------------------------------------------
|
|
|
|
// get rid of the spurious tooltip produced by the alt attribute on images
|
|
IE7.HTML.addRecalc("img", function(img) {
|
|
if (img.alt && !img.title) img.title = "";
|
|
});
|
|
|
|
// =========================================================================
|
|
// ie8-layout.js
|
|
// =========================================================================
|
|
|
|
IE7.CSS.addRecalc("border-spacing", NUMERIC, function(element) {
|
|
if (element.currentStyle.borderCollapse != "collapse") {
|
|
element.cellSpacing = getPixelValue(element, element.currentStyle["border-spacing"]);
|
|
}
|
|
});
|
|
IE7.CSS.addRecalc("box-sizing", "content-box", IE7.Layout.boxSizing);
|
|
IE7.CSS.addRecalc("box-sizing", "border-box", IE7.Layout.borderBox);
|
|
|
|
// =========================================================================
|
|
// ie8-graphics.js
|
|
// =========================================================================
|
|
|
|
IE7.CSS.addFix(/opacity\s*:\s*([\d.]+)/, function(match, value) {
|
|
return "zoom:1;filter:Alpha(opacity=" + ((value * 100) || 1) + ")";
|
|
});
|
|
|
|
// fix object[type=image/*]
|
|
var IMAGE = /^image/i;
|
|
IE7.HTML.addRecalc("object", function(element) {
|
|
if (IMAGE.test(element.type)) {
|
|
element.body.style.cssText = "margin:0;padding:0;border:none;overflow:hidden";
|
|
return 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();
|
|
})();
|
|
|
|
|
|
})();
|