angular.js/src/Angular.js
2010-07-26 15:32:08 -07:00

385 lines
11 KiB
JavaScript

////////////////////////////////////
if (typeof document.getAttribute == 'undefined')
document.getAttribute = function() {};
var consoleNode,
PRIORITY_FIRST = -99999,
PRIORITY_WATCH = -1000,
PRIORITY_LAST = 99999,
PRIORITY = {'FIRST': PRIORITY_FIRST, 'LAST': PRIORITY_LAST, 'WATCH':PRIORITY_WATCH},
NOOP = 'noop',
NG_EXCEPTION = 'ng-exception',
NG_VALIDATION_ERROR = 'ng-validation-error',
jQuery = window['jQuery'] || window['$'], // weirdness to make IE happy
_ = window['_'],
msie = !!/(msie) ([\w.]+)/.exec(lowercase(navigator.userAgent)),
jqLite = jQuery || jqLiteWrap,
slice = Array.prototype.slice,
error = window['console'] ? bind(window['console'], window['console']['error'] || noop) : noop,
angular = window['angular'] || (window['angular'] = {}),
angularTextMarkup = extensionMap(angular, 'textMarkup'),
angularAttrMarkup = extensionMap(angular, 'attrMarkup'),
angularDirective = extensionMap(angular, 'directive'),
angularWidget = extensionMap(angular, 'widget', lowercase),
angularValidator = extensionMap(angular, 'validator'),
angularFilter = extensionMap(angular, 'filter'),
angularFormatter = extensionMap(angular, 'formatter'),
angularService = extensionMap(angular, 'service'),
angularCallbacks = extensionMap(angular, 'callbacks'),
nodeName;
function foreach(obj, iterator, context) {
var key;
if (obj) {
if (isFunction(obj)){
for (key in obj) {
if (key != 'prototype' && key != 'length' && key != 'name' && obj.hasOwnProperty(key)) {
iterator.call(context, obj[key], key);
}
}
} else if (obj.forEach) {
obj.forEach(iterator, context);
} else if (isObject(obj) && isNumber(obj.length)) {
for (key = 0; key < obj.length; key++)
iterator.call(context, obj[key], key);
} else {
for (key in obj)
iterator.call(context, obj[key], key);
}
}
return obj;
}
function foreachSorted(obj, iterator, context) {
var keys = [];
for (var key in obj) keys.push(key);
keys.sort();
for ( var i = 0; i < keys.length; i++) {
iterator.call(context, obj[keys[i]], keys[i]);
}
return keys;
}
function extend(dst) {
foreach(arguments, function(obj){
if (obj !== dst) {
foreach(obj, function(value, key){
dst[key] = value;
});
}
});
return dst;
}
function inherit(parent, extra) {
return extend(new (extend(function(){}, {prototype:parent}))(), extra);
};
function noop() {}
function identity($) {return $;}
function extensionMap(angular, name, transform) {
var extPoint;
return angular[name] || (extPoint = angular[name] = function (name, fn, prop){
name = (transform || identity)(name);
if (isDefined(fn)) {
extPoint[name] = extend(fn, prop || {});
}
return extPoint[name];
});
}
function jqLiteWrap(element) {
// for some reasons the parentNode of an orphan looks like null but its typeof is object.
if (element) {
if (isString(element)) {
var div = document.createElement('div');
div.innerHTML = element;
element = new JQLite(div.childNodes);
} else if (!(element instanceof JQLite) && isElement(element)) {
element = new JQLite(element);
}
}
return element;
}
function isUndefined(value){ return typeof value == 'undefined'; }
function isDefined(value){ return typeof value != 'undefined'; }
function isObject(value){ return typeof value == 'object';}
function isString(value){ return typeof value == 'string';}
function isNumber(value){ return typeof value == 'number';}
function isArray(value) { return value instanceof Array; }
function isFunction(value){ return typeof value == 'function';}
function isTextNode(node) { return nodeName(node) == '#text'; }
function lowercase(value){ return isString(value) ? value.toLowerCase() : value; }
function uppercase(value){ return isString(value) ? value.toUpperCase() : value; }
function trim(value) { return isString(value) ? value.replace(/^\s*/, '').replace(/\s*$/, '') : value; }
function isElement(node) {
return node && (node.nodeName || node instanceof JQLite || (jQuery && node instanceof jQuery));
}
function HTML(html) {
this.html = html;
}
if (msie) {
nodeName = function(element) {
element = element[0] || element;
return (element.scopeName && element.scopeName != 'HTML' ) ? uppercase(element.scopeName + ':' + element.nodeName) : element.nodeName;
};
} else {
nodeName = function(element) {
return (element[0] || element).nodeName;
};
}
function isVisible(element) {
var rect = element[0].getBoundingClientRect(),
width = (rect.width || (rect.right||0 - rect.left||0)),
height = (rect.height || (rect.bottom||0 - rect.top||0));
return width>0 && height>0;
}
function map(obj, iterator, context) {
var results = [];
foreach(obj, function(value, index, list) {
results.push(iterator.call(context, value, index, list));
});
return results;
}
function size(obj) {
var size = 0;
if (obj) {
if (isNumber(obj.length)) {
return obj.length;
} else if (isObject(obj)){
for (key in obj)
size++;
}
}
return size;
}
function includes(array, obj) {
for ( var i = 0; i < array.length; i++) {
if (obj === array[i]) return true;
}
return false;
}
function indexOf(array, obj) {
for ( var i = 0; i < array.length; i++) {
if (obj === array[i]) return i;
}
return -1;
}
function isLeafNode (node) {
if (node) {
switch (node.nodeName) {
case "OPTION":
case "PRE":
case "TITLE":
return true;
}
}
return false;
}
function copy(source, destination){
if (!destination) {
if (source) {
if (isArray(source)) {
return copy(source, []);
} else if (isObject(source)) {
return copy(source, {});
}
}
return source;
} else {
if (isArray(source)) {
while(destination.length) {
destination.pop();
}
for ( var i = 0; i < source.length; i++) {
destination.push(copy(source[i]));
}
} else {
foreach(destination, function(value, key){
delete destination[key];
});
for ( var key in source) {
destination[key] = copy(source[key]);
}
}
return destination;
}
}
function equals(o1, o2) {
if (o1 == o2) return true;
var t1 = typeof o1, t2 = typeof o2, length, key, keySet;
if (t1 == t2 && t1 == 'object') {
if (o1 instanceof Array) {
if ((length = o1.length) == o2.length) {
for(key=0; key<length; key++) {
if (!equals(o1[key], o2[key])) return false;
}
return true;
}
} else {
keySet = {};
for(key in o1) {
if (key.charAt(0) !== '$' && !equals(o1[key], o2[key])) return false;
keySet[key] = true;
}
for(key in o2) {
if (key.charAt(0) !== '$' && keySet[key] !== true) return false;
}
return true;
}
}
return false;
}
function setHtml(node, html) {
if (isLeafNode(node)) {
if (msie) {
node.innerText = html;
} else {
node.textContent = html;
}
} else {
node.innerHTML = html;
}
}
function escapeHtml(html) {
if (!html || !html.replace)
return html;
return html.
replace(/&/g, '&amp;').
replace(/</g, '&lt;').
replace(/>/g, '&gt;');
}
function isRenderableElement(element) {
var name = element && element[0] && element[0].nodeName;
return name && name.charAt(0) != '#' &&
!includes(['TR', 'COL', 'COLGROUP', 'TBODY', 'THEAD', 'TFOOT'], name);
}
function elementError(element, type, error) {
while (!isRenderableElement(element)) {
element = element.parent() || jqLite(document.body);
}
if (element[0]['$NG_ERROR'] !== error) {
element[0]['$NG_ERROR'] = error;
if (error) {
element.addClass(type);
element.attr(type, error);
} else {
element.removeClass(type);
element.removeAttr(type);
}
}
}
function escapeAttr(html) {
if (!html || !html.replace)
return html;
return html.replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/\"/g,
'&quot;');
}
function bind(_this, _function) {
var curryArgs = slice.call(arguments, 2, arguments.length);
return curryArgs.length == 0 ?
function() {
return _function.apply(_this, arguments);
} :
function() {
return _function.apply(_this, curryArgs.concat(slice.call(arguments, 0, arguments.length)));
};
}
function outerHTML(node) {
var temp = document.createElement('div');
temp.appendChild(node);
var outerHTML = temp.innerHTML;
temp.removeChild(node);
return outerHTML;
}
function toBoolean(value) {
if (value && value.length !== 0) {
var v = lowercase("" + value);
value = !(v == 'f' || v == '0' || v == 'false' || v == 'no' || v == 'n' || v == '[]');
} else {
value = false;
}
return value;
}
function merge(src, dst) {
for ( var key in src) {
var value = dst[key];
var type = typeof value;
if (type == 'undefined') {
dst[key] = fromJson(toJson(src[key]));
} else if (type == 'object' && value.constructor != array &&
key.substring(0, 1) != "$") {
merge(src[key], value);
}
}
}
function compile(element, parentScope) {
var compiler = new Compiler(angularTextMarkup, angularAttrMarkup, angularDirective, angularWidget),
$element = jqLite(element),
parent = extend({}, parentScope);
parent.$element = $element;
return compiler.compile($element)($element, parent);
}
/////////////////////////////////////////////////
function parseKeyValue(keyValue) {
var obj = {}, key_value, key;
foreach((keyValue || "").split('&'), function(keyValue){
if (keyValue) {
key_value = keyValue.split('=');
key = decodeURIComponent(key_value[0]);
obj[key] = key_value[1] ? decodeURIComponent(key_value[1]) : true;
}
});
return obj;
}
function toKeyValue(obj) {
var parts = [];
foreach(obj, function(value, key){
parts.push(encodeURIComponent(key) + '=' + encodeURIComponent(value));
});
return parts.length ? parts.join('&') : '';
}
function angularInit(config){
if (config.autobind) {
var scope = compile(window.document, null, {'$config':config});
// TODO default to the source of angular.js
scope.$browser.addCss('css/angular.css');
scope.$init();
}
}
function angularJsConfig(document) {
var filename = /(.*)\/angular(-(.*))?.js(#(.*))?/,
scripts = document.getElementsByTagName("script"),
match;
for(var j = 0; j < scripts.length; j++) {
match = (scripts[j].src || "").match(filename);
if (match) {
return match[5];
}
}
return "";
}