support MSIE 8 until after app load, and MSIE 8 with Chrome Frame beyond that

This commit is contained in:
rlx 2011-09-03 13:18:20 +00:00
commit 5818bd5edc
373 changed files with 11048 additions and 29979 deletions

View file

@ -40,6 +40,108 @@ Some conventions:
// todo: check http://ejohn.org/blog/ecmascript-5-strict-mode-json-and-more/
// also see https://github.com/tlrobinson/narwhal/blob/master/lib/util.js
// see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/filter
if (!Array.prototype.filter) {
Array.prototype.filter = function(fn, that) {
if (this === void 0 || this === null || typeof fn !== 'function') {
throw new TypeError();
}
var arr = Object(this),
i,
len = arr.length >>> 0,
ret = [],
val;
for (i = 0; i < len; i++) {
// save val in case fn mutates it
if (i in arr && fn.call(that, val = arr[i], i, arr)) {
ret.push(val);
}
}
return ret;
};
}
// see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/forEach
if (!Array.prototype.forEach) {
Array.prototype.forEach = function(fn, that) {
if (this === void 0 || this === null || typeof fn !== 'function') {
throw new TypeError();
}
var arr = Object(this),
i,
len = arr.length >>> 0;
for (i = 0; i < len; i++) {
if (i in arr) {
fn.call(that, arr[i], i, arr);
}
}
}
}
// see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/indexOf
if (!Array.prototype.indexOf) {
Array.prototype.indexOf = function(val) {
if (this === void 0 || this === null) {
throw new TypeError();
}
var arr = Object(this),
i,
len = arr.length >>> 0;
ret = -1;
for (i = 0; i < len; i++) {
if (i in arr && arr[i] === val) {
ret = val;
break
}
}
return ret;
}
}
// see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/map
if (!Array.prototype.map) {
Array.prototype.map = function(fn, that) {
if (this === void 0 || this === null || typeof fn !== 'function') {
throw new TypeError();
}
var arr = Object(this),
i,
len = arr.length >>> 0,
ret = new Array(len);
for (i = 0; i < len; i++) {
if (i in arr) {
ret[i] == fn.call(that, arr[i], i, arr);
}
}
return ret;
}
}
// see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/reduce
if (!Array.prototype.reduce) {
Array.prototype.reduce = function reduce(fn, ret) {
if (this === void 0 || this === null || typeof fn !== 'function') {
throw new TypeError();
}
var arr = Object(this),
i,
len = this.length;
if (!len && ret === void 0) {
throw new TypeError();
}
if (ret === void 0) {
ret = arr[0];
i = 1;
}
for (i = i || 0; i < len ; ++i) {
if (i in arr) {
ret = fn.call(void 0, ret, arr[i], i, arr);
}
}
return ret;
};
}
//@ Core -----------------------------------------------------------------------
/*@
@ -447,10 +549,12 @@ Ox.forEach <f> forEach loop
<code>(value, key)</code> (like <code>[].forEach()</code>, unlike
<code>$.each()</code>).
(collection, callback) <a|o|s> The collection
(collection, callback, includePrototype) <a|o|s> The collection
collection <a|o|s> An array, object or string
callback <f> Callback function
value <*> Value
key <n|s> Key
includePrototype <b|false> If true, include prototype properties
<script>
Ox.test.string = "";
Ox.forEach(["f", "o", "o"], function(v, i) { Ox.test.string += i; });
@ -460,22 +564,20 @@ Ox.forEach <f> forEach loop
> Ox.test.string
"012abcfoo"
@*/
Ox.forEach = function(obj, fn) {
var isObject = Ox.isObject(obj), key;
if (Ox.isArguments(obj)) {
// Safari will not loop through an arguments array
obj = Ox.makeArray(obj);
}
for (key in obj) {
Ox.forEach = function(col, fn, includePrototype) {
var isObject = Ox.isObject(col), key;
// Safari will not loop through an arguments array
col = Ox.isArguments(col) ? Ox.makeArray(col) : col;
for (key in col) {
key = isObject ? key : parseInt(key);
// fixme: some code somewhere (jQuery wrapper?) relies on looping over the prototype
// ... but the hasOwnProperty call should be uncommented!
// +fixme: fn.call(context, obj[key], key, obj) may be more standard...
if (/*hasOwnProperty.call(obj, key) && */fn(obj[key], key) === false) {
// fixme: fn.call(context, obj[key], key, obj) may be more standard...
if ((
includePrototype || Object.hasOwnProperty.call(col, key)
) && fn(col[key], key) === false) {
break;
}
}
return obj;
return col;
};
/*@
@ -714,8 +816,20 @@ Ox.makeArray <f> Takes an array-like object and returns a true array
["f", "o", "o"]
@*/
Ox.makeArray = function(obj) {
return Array.prototype.slice.call(obj);
Ox.makeArray = /MSIE/.test(navigator.userAgent) ? function(col) {
var i, len, ret = [];
try {
ret = Array.prototype.slice.call(col);
} catch(e) {
// handle MSIE NodeLists
len = col.length;
for (i = 0; i < len; i++) {
ret[i] = col[i];
}
}
return ret;
} : function(col) {
return Array.prototype.slice.call(col);
}
/*@
@ -765,9 +879,9 @@ Ox.map = function(obj, fn) {
var isObject = Ox.isObject(obj),
ret = isObject ? {} : [];
Ox.forEach(obj, function(val, key) {
var v;
if ((v = fn(val, key)) !== null) {
ret[isObject ? key : ret.length] = v;
var map;
if ((map = fn(val, key)) !== null) {
ret[isObject ? key : ret.length] = map;
}
});
return ret;
@ -1177,7 +1291,7 @@ Ox.SHORT_MONTHS = Ox.MONTHS.map(function(val) {
return val.substr(0, 3);
});
//@ Ox.PATH <str> Path of Ox.js
Ox.PATH = Array.prototype.slice.apply(
Ox.PATH = Ox.makeArray(
document.getElementsByTagName('script')
).filter(function(element) {
return /Ox\.js$/.test(element.src);
@ -4038,15 +4152,19 @@ Ox.loadFile = (function() {
type == 'css' ? 'link' : 'script'
);
element[type == 'css' ? 'href' : 'src'] = file + '?' + Ox.random(1000000);
element.type = type == 'css' ?
'text/css' : 'text/javascript';
if (type == 'css') {
element.rel = 'stylesheet';
waitForCSS();
element.type = type == 'css' ? 'text/css' : 'text/javascript';
if (/MSIE/.test(navigator.userAgent)) {
// fixme: find a way to check if css/js have loaded in msie
setTimeout(addFileToCache, 2500);
} else {
element.onload = addFileToCache;
if (type == 'css') {
element.rel = 'stylesheet';
waitForCSS();
} else {
element.onload = addFileToCache;
}
}
document.head.appendChild(element);
document.getElementsByTagName('head')[0].appendChild(element);
} else {
addFileToCache();
}
@ -4066,7 +4184,7 @@ Ox.loadFile = (function() {
}
}
function findFileInHead() {
return Array.prototype.slice.apply(
return Ox.makeArray(
document.getElementsByTagName(type == 'css' ? 'link' : 'script')
).map(function(element) {
return element[type == 'css' ? 'href' : 'src'] == file;
@ -4354,13 +4472,13 @@ Ox.toTitleCase <f> Returns a string with capitalized words
'Apple Releases iPhone, IBM Stock Plummets'
@*/
Ox.toTitleCase = function(str) {
return Ox.map(str.split(' '), function(v) {
var sub = v.substr(1),
return Ox.map(str.split(' '), function(val) {
var sub = val.substr(1),
low = sub.toLowerCase();
if (sub == low) {
v = v.substr(0, 1).toUpperCase() + low;
val = val.substr(0, 1).toUpperCase() + low;
}
return v;
return val;
}).join(' ');
};
@ -4526,7 +4644,9 @@ Ox.isArguments <f> Tests if a value is an arguments "array"
> Ox.isArguments((function() { return arguments; }()))
true
@*/
Ox.isArguments = function(val) {
Ox.isArguments = /MSIE/.test(navigator.userAgent) ? function(val) {
return !!(val && Object.hasOwnProperty.call(val, 'callee'));
} : function(val) {
return !!(val && val.toString() == '[object Arguments]');
}
@ -4739,8 +4859,8 @@ Ox.isObject <f> Tests if a value is a an object
@*/
Ox.isObject = function(val) {
return typeof val == 'object' && !Ox.isArguments(val) &&
!Ox.isArray(val) && !Ox.isDate(val) && !Ox.isNull(val);
return typeof val == 'object' && !Ox.isArguments(val)
&& !Ox.isArray(val) && !Ox.isDate(val) && !Ox.isNull(val);
};
/*@