1
0
mirror of https://github.com/haiwen/seahub.git synced 2025-08-17 14:37:58 +00:00
seahub/media/aloha-0.22.7/lib/aloha/ecma5shims.js
llj 720ac28c22 [aloha] upgraded to 0.22.7 and added textcolor plugin
* textcolor: fixed plugin bugs, added translation for zh
* image: fixed default.jpg src bug
* added 'ru' support for seaf edit
* rm aloha-0.22.3 and ununsed files in aloha-0.22.7
2013-01-15 14:48:04 +08:00

327 lines
8.5 KiB
JavaScript

/**
* ecma5schims.js - Shim for ECMA5 compatibility
* (http://en.wikipedia.org/wiki/Shim_%28computing%29)
*
* A shim library that implements common functions that are missing on some
* environments in order to complete ECMA5 compatibility across all major
* browsers.
*
* TODO: This code needs to be refactored so as to conform to Aloha coding
* standards. It is also severly lacking in documentation. Please take
* note of: https://github.com/alohaeditor/Aloha-Editor/wiki/Commit-Checklist .
*/
define([], function () {
'use strict';
var $_;
var shims = {
// Function bind
bind: function (owner) {
var obj = this.obj || this;
var native_method = Function.prototype.bind;
var args = Array.prototype.slice.call(arguments, 1);
if (native_method) {
return native_method.apply(obj, arguments);
}
return function () {
return obj.apply(owner, arguments.length === 0 ? args : args.concat(Array.prototype.slice.call(arguments)));
};
},
// String trim
trim: function () {
var obj = this.obj || this;
var native_method = String.prototype.trim;
if (native_method) {
return native_method.call(obj);
}
return obj.replace(/^\s+/, '').replace(/\s+$/, '');
},
// Array methods
// i optional
indexOf: function (find, i) {
var obj = this.obj || this;
var native_method = Array.prototype.indexOf;
if (native_method) {
return native_method.call(obj, find, i);
}
if (i === undefined) {
i = 0;
}
if (i < 0) {
i += obj.length;
}
if (i < 0) {
i = 0;
}
var n;
for (n = obj.length; i < n; i++) {
if (undefined !== obj[i] && obj[i] === find) {
return i;
}
}
return -1;
},
// that optional
forEach: function (action, that) {
var obj = this.obj || this;
var native_method = Array.prototype.forEach;
if (native_method) {
return native_method.call(obj, action, that);
}
var i, n;
for (i = 0, n = obj.length; i < n; i++) {
if (undefined !== obj[i]) {
action.call(that, obj[i], i, obj);
}
}
},
// that optional
// chain optional
map: function (mapper, that, chain) {
var obj = this.obj || this;
var native_method = Array.prototype.map;
var returnWrapper = (typeof arguments[arguments.length - 1] == "boolean") ? Array.prototype.pop.call(arguments) : false;
var result = [];
if (native_method) {
result = native_method.call(obj, mapper, that);
} else {
var other = [];
var i, n;
for (i = 0, n = obj.length; i < n; i++) {
if (undefined !== obj[i]) {
other[i] = mapper.call(that, obj[i], i, obj);
}
}
result = other;
}
return returnWrapper ? $_(result) : result;
},
// that optional
// chain optional
filter: function (filterFunc, that, chain) {
var obj = this.obj || this;
var native_method = Array.prototype.filter;
var returnWrapper = (typeof arguments[arguments.length - 1] == "boolean") ? Array.prototype.pop.call(arguments) : false;
var result = [];
if (native_method) {
result = native_method.call(obj, filterFunc, that);
} else {
var other = [],
v,
i,
n;
for (i = 0, n = obj.length; i < n; i++) {
if (undefined !== obj[i] && filterFunc.call(that, v = obj[i], i, obj)) {
other.push(v);
}
}
result = other;
}
return returnWrapper ? $_(result) : result;
},
// that optional
every: function (tester, that) {
var obj = this.obj || this;
var native_method = Array.prototype.every;
if (native_method) {
return native_method.call(obj, tester, that);
}
var i, n;
for (i = 0, n = obj.length; i < n; i++) {
if (undefined !== obj[i] && !tester.call(that, obj[i], i, obj)) {
return false;
}
}
return true;
},
// that optional
some: function (tester, that) {
var obj = this.obj || this;
var native_method = Array.prototype.some;
if (native_method) {
return native_method.call(obj, tester, that);
}
var i, n;
for (i = 0, n = obj.length; i < n; i++) {
if (undefined !== obj[i] && tester.call(that, obj[i], i, obj)) {
return true;
}
}
return false;
},
// Since IE7 doesn't support 'hasAttribute' method on nodes
// TODO: raise an exception if the object is not an node
hasAttribute: function (attr) {
var obj = this.obj || this;
var native_method = obj.hasAttribute;
if (native_method) {
return obj.hasAttribute(attr);
}
return !!obj.getAttribute(attr);
}
};
$_ = function (obj) {
var Wrapper = function () {};
Wrapper.prototype = shims;
var wrapper_instance = new Wrapper();
wrapper_instance.obj = obj;
return wrapper_instance;
};
var shim;
for (shim in shims) {
if (shims.hasOwnProperty(shim)) {
$_[shim] = shims[shim];
}
}
// Node constants
// http://www.w3.org/TR/DOM-Level-3-Core/core.html#ID-1841493061
if (typeof window.Node != 'undefined') {
$_.Node = window.Node;
} else {
$_.Node = {
'ELEMENT_NODE': 1,
'ATTRIBUTE_NODE': 2,
'TEXT_NODE': 3,
'CDATA_SECTION_NODE': 4,
'ENTITY_REFERENCE_NODE': 5,
'ENTITY_NODE': 6,
'PROCESSING_INSTRUCTION_NODE': 7,
'COMMENT_NODE': 8,
'DOCUMENT_NODE': 9,
'DOCUMENT_TYPE_NODE': 10,
'DOCUMENT_FRAGMENT_NODE': 11,
'NOTATION_NODE': 12,
//The two nodes are disconnected. Order between disconnected nodes is always implementation-specific.
'DOCUMENT_POSITION_DISCONNECTED': 0x01,
//The second node precedes the reference node.
'DOCUMENT_POSITION_PRECEDING': 0x02,
//The node follows the reference node.
'DOCUMENT_POSITION_FOLLOWING': 0x04,
//The node contains the reference node. A node which contains is always preceding, too.
'DOCUMENT_POSITION_CONTAINS': 0x08,
//The node is contained by the reference node. A node which is contained is always following, too.
'DOCUMENT_POSITION_CONTAINED_BY': 0x10,
//The determination of preceding versus following is implementation-specific.
'DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC': 0x20
};
}
//node.ownerDocument gives the document object, which isn't the right info for a disconnect
function getRootParent(node) {
var parent = null;
if (node) {
do {
parent = node;
} while (null != (node = node.parentNode));
}
return parent;
}
//Compare Position - MIT Licensed, John Resig; http://ejohn.org/blog/comparing-document-position/
//Already checked for equality and disconnect
function comparePosition(node1, node2) {
return (node1.contains(node2) && 16) + (node2.contains(node1) && 8) + (node1.sourceIndex >= 0 && node2.sourceIndex >= 0 ? (node1.sourceIndex < node2.sourceIndex && 4) + (node1.sourceIndex > node2.sourceIndex && 2) : 1);
}
//get a node with a sourceIndex to use
function getUseNode(node) {
//if the node already has a sourceIndex, use that node
if (null != node.sourceIndex) {
return node;
}
//otherwise, insert a comment (which has a sourceIndex but minimal DOM impact) before the node and use that
return node.parentNode.insertBefore(document.createComment(""), node);
}
// http://www.w3.org/TR/DOM-Level-3-Core/core.html#Node3-compareDocumentPosition
// FIXME: Check if the DOMNode prototype can be set.
$_.compareDocumentPosition = function (node1, node2) {
if (document.documentElement.compareDocumentPosition) {
return node1.compareDocumentPosition(node2);
}
if (!document.documentElement.contains) {
throw 'neither compareDocumentPosition nor contains is supported by this browser.';
}
if (node1 == node2) {
return 0;
}
//if they don't have the same parent, there's a disconnect
if (getRootParent(node1) != getRootParent(node2)) {
return 1;
}
//use this if both nodes have a sourceIndex (text nodes don't)
if (null != node1.sourceIndex && null != node2.sourceIndex) {
return comparePosition(node1, node2);
}
//document will definitely contain the other node
if (node1 == document) {
return 20;
}
if (node2 == document) {
return 10;
}
//get sourceIndexes to use for both nodes
var useNode1 = getUseNode(node1),
useNode2 = getUseNode(node2);
//call this function again to get the result
var result = comparePosition(useNode1, useNode2);
//clean up if needed
if (node1 != useNode1) {
useNode1.parentNode.removeChild(useNode1);
}
if (node2 != useNode2) {
useNode2.parentNode.removeChild(useNode2);
}
return result;
};
$_.getComputedStyle = function (node, style) {
if (window.getComputedStyle) {
return window.getComputedStyle(node, style);
}
if (node.currentStyle) {
return node.currentStyle;
}
return null;
};
return $_;
});