diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/Angular.js | 80 | ||||
| -rw-r--r-- | src/Compiler.js | 12 | ||||
| -rw-r--r-- | src/Formatters.js | 4 | ||||
| -rw-r--r-- | src/Parser.js | 12 | ||||
| -rw-r--r-- | src/Resource.js | 8 | ||||
| -rw-r--r-- | src/Scope.js | 1 | ||||
| -rw-r--r-- | src/Validators.js | 4 | ||||
| -rw-r--r-- | src/Widgets.js | 28 | ||||
| -rw-r--r-- | src/apis.js | 62 | ||||
| -rw-r--r-- | src/jqLite.js | 15 |
10 files changed, 138 insertions, 88 deletions
diff --git a/src/Angular.js b/src/Angular.js index c3562e84..12293ddb 100644 --- a/src/Angular.js +++ b/src/Angular.js @@ -1,25 +1,13 @@ if (typeof document.getAttribute == 'undefined') document.getAttribute = function() {}; -function noop() {} -function identity($) {return $;} if (!window['console']) window['console']={'log':noop, 'error':noop}; -function extensionMap(angular, name) { - var extPoint; - return angular[name] || (extPoint = angular[name] = function (name, fn, prop){ - if (isDefined(fn)) { - extPoint[name] = extend(fn, prop || {}); - } - return extPoint[name]; - }); -} - var consoleNode, NOOP = 'noop', jQuery = window['jQuery'] || window['$'], // weirdness to make IE happy _ = window['_'], - jqLite = jQuery, + jqLite = jQuery || jqLiteWrap, slice = Array.prototype.slice, angular = window['angular'] || (window['angular'] = {}), angularTextMarkup = extensionMap(angular, 'textMarkup'), @@ -44,7 +32,7 @@ function foreach(obj, iterator, context) { if (obj) { if (obj.forEach) { obj.forEach(iterator, context); - } else if (obj instanceof Array) { + } else if (isObject(obj) && isNumber(obj.length)) { for (key = 0; key < obj.length; key++) iterator.call(context, obj[key], key); } else { @@ -55,22 +43,66 @@ function foreach(obj, iterator, context) { return obj; } -function extend(dst, obj) { - foreach(obj, function(value, key){ - dst[key] = value; +function extend(dst) { + foreach(arguments, function(obj){ + if (obj !== dst) { + foreach(obj, function(value, key){ + dst[key] = value; + }); + } }); return dst; } +function noop() {} +function identity($) {return $;} +function extensionMap(angular, name) { + var extPoint; + return angular[name] || (extPoint = angular[name] = function (name, fn, prop){ + if (isDefined(fn)) { + extPoint[name] = extend(fn, prop || {}); + } + return extPoint[name]; + }); +} + +function jqLiteWrap(element) { + if (typeof element == 'string') { + var div = document.createElement('div'); + div.innerHTML = element; + element = div.childNodes[0]; + } + return element instanceof JQLite ? element : new JQLite(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 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 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; @@ -78,6 +110,13 @@ function includes(array, obj) { return false; } +function indexOf(array, obj) { + for ( var i = 0; i < array.length; i++) { + if (obj === array[i]) return i; + } + return -1; +} + function log(a, b, c){ var console = window['console']; switch(arguments.length) { @@ -157,11 +196,14 @@ function copy(source, destination){ destination.pop(); } } else { - foreach(function(value, key){ + foreach(destination, function(value, key){ delete destination[key]; }); } - return $.extend(true, destination, source); + foreach(source, function(value, key){ + destination[key] = isArray(value) ? copy(value, []) : (isObject(value) ? copy(value, {}) : value); + }); + return destination; } }; diff --git a/src/Compiler.js b/src/Compiler.js index 4f30521b..923f7b2f 100644 --- a/src/Compiler.js +++ b/src/Compiler.js @@ -73,11 +73,12 @@ function eachNode(element, fn){ } function eachAttribute(element, fn){ - var i, attrs = element[0].attributes || [], size = attrs.length, chld, attr; + var i, attrs = element[0].attributes || [], size = attrs.length, chld, attr, attrValue = {}; for (i = 0; i < size; i++) { var attr = attrs[i]; - fn(attr.name, attr.value); + attrValue[attr.name] = attr.value; } + foreach(attrValue, fn); } function Compiler(textMarkup, attrMarkup, directives, widgets){ @@ -92,12 +93,15 @@ Compiler.prototype = { rawElement = jqLite(rawElement); var template = this.templatize(rawElement) || new Template(); return function(element, parentScope){ + parentScope = parentScope || {}; var scope = createScope(parentScope); + parentScope.$root = parentScope.$root || scope; return extend(scope, { $element:element, $init: function() { template.init(element, scope); scope.$eval(); + return scope; } }); }; @@ -132,12 +136,12 @@ Compiler.prototype = { }); // Process attributes/directives - eachAttribute(element, function(name, value){ + eachAttribute(element, function(value, name){ foreach(self.attrMarkup, function(markup){ markup.call(selfApi, value, name, element); }); }); - eachAttribute(element, function(name, value){ + eachAttribute(element, function(value, name){ var directive = directives[name]; if (!exclusive && directive) { if (directive.exclusive) { diff --git a/src/Formatters.js b/src/Formatters.js index f2d5d33e..402e8a2b 100644 --- a/src/Formatters.js +++ b/src/Formatters.js @@ -9,7 +9,7 @@ extend(angularFormatter, { function(obj) { return obj ? obj.join(", ") : obj; }, function(value) { var list = []; - foreach(value.split(','), function(item){ + foreach((value || '').split(','), function(item){ item = trim(item); if (item) list.push(item); }); @@ -18,6 +18,6 @@ extend(angularFormatter, { ), 'trim':formater( - function(obj) { return obj ? $.trim("" + obj) : ""; } + function(obj) { return obj ? trim("" + obj) : ""; } ) }); diff --git a/src/Parser.js b/src/Parser.js index 81a2afdc..ef1465a0 100644 --- a/src/Parser.js +++ b/src/Parser.js @@ -558,14 +558,14 @@ Parser.prototype = { } var statements = this.statements(); this.consume("}"); - return function(self){ + return function(self) { return function($){ - var scope = new Scope(self.scope.state); - scope.set('$', $); + var scope = createScope(self.state); + scope['$'] = $; for ( var i = 0; i < args.length; i++) { - scope.set(args[i], arguments[i]); + scope.$set(args[i], arguments[i]); } - return statements({scope:scope}); + return statements({scope:{get:scope.$get, set:scope.$set}}); }; }; }, @@ -573,7 +573,7 @@ Parser.prototype = { fieldAccess: function(object) { var field = this.expect().text; var fn = function (self){ - return Scope.getter(object(self), field); + return getter(object(self), field); }; fn.isAssignable = field; return fn; diff --git a/src/Resource.js b/src/Resource.js index 971ad6e5..27ce8aa9 100644 --- a/src/Resource.js +++ b/src/Resource.js @@ -46,11 +46,11 @@ ResourceFactory.prototype = { route: function(url, paramDefaults, actions){ var self = this; var route = new Route(url); - actions = $.extend({}, ResourceFactory.DEFAULT_ACTIONS, actions); + actions = extend({}, ResourceFactory.DEFAULT_ACTIONS, actions); function extractParams(data){ var ids = {}; foreach(paramDefaults || {}, function(value, key){ - ids[key] = value.charAt && value.charAt(0) == '@' ? Scope.getter(data, value.substr(1)) : value; + ids[key] = value.charAt && value.charAt(0) == '@' ? getter(data, value.substr(1)) : value; }); return ids; } @@ -83,7 +83,7 @@ ResourceFactory.prototype = { } var value = action.isArray ? [] : new Resource(data); - self.xhr(action.method, route.url($.extend({}, action.params || {}, extractParams(data), params)), data, function(response) { + self.xhr(action.method, route.url(extend({}, action.params || {}, extractParams(data), params)), data, function(response) { if (action.isArray) { foreach(response, function(item){ value.push(new Resource(item)); @@ -97,7 +97,7 @@ ResourceFactory.prototype = { }; Resource.bind = function(additionalParamDefaults){ - return self.route(url, $.extend({}, paramDefaults, additionalParamDefaults), actions); + return self.route(url, extend({}, paramDefaults, additionalParamDefaults), actions); }; if (!isGet) { diff --git a/src/Scope.js b/src/Scope.js index 6ba6aa8e..3e225653 100644 --- a/src/Scope.js +++ b/src/Scope.js @@ -61,6 +61,7 @@ function expressionCompile(exp){ function parserNewScopeAdapter(fn) { return function(){ return fn({ + state: this, scope: { set: this.$set, get: this.$get diff --git a/src/Validators.js b/src/Validators.js index cdff5e1a..662145c0 100644 --- a/src/Validators.js +++ b/src/Validators.js @@ -91,12 +91,12 @@ foreach({ obj[lastKey] = text; if (state === undefined) { // we have never seen this before, Request it - jQuery(obj).addClass('ng-input-indicator-wait'); + jqLite(obj).addClass('ng-input-indicator-wait'); state = stateCache[text] = null; asynchronousFn(text, function(error){ state = stateCache[text] = error ? error : false; if (stateCache[obj[lastKey]] !== null) { - jQuery(obj).removeClass('ng-input-indicator-wait'); + jqLite(obj).removeClass('ng-input-indicator-wait'); } updateView(); }); diff --git a/src/Widgets.js b/src/Widgets.js index 42b9e916..b5222ac7 100644 --- a/src/Widgets.js +++ b/src/Widgets.js @@ -18,7 +18,7 @@ function compileValidator(expr) { return new Parser(expr).validator()(); } -function valueAccessor(element) { +function valueAccessor(scope, element) { var validatorName = element.attr('ng-validate') || NOOP, validator = compileValidator(validatorName), required = element.attr('ng-required'), @@ -26,7 +26,7 @@ function valueAccessor(element) { required = required || required == ''; if (!validator) throw "Validator named '" + validatorName + "' not found."; function validate(value) { - var error = required && !trim(value) ? "Required" : validator.call(this, value); + var error = required && !trim(value) ? "Required" : validator({self:scope, scope:{get:scope.$get, set:scope.$set}}, value); if (error !== lastError) { if (error) { element.addClass(NG_VALIDATION_ERROR); @@ -45,23 +45,31 @@ function valueAccessor(element) { }; } -function checkedAccessor(element) { +function checkedAccessor(scope, element) { var domElement = element[0]; return { - get: function(){ return !!domElement.checked; }, - set: function(value){ domElement.checked = !!value; } + get: function(){ + return !!domElement.checked; + }, + set: function(value){ + domElement.checked = !!value; + } }; } -function radioAccessor(element) { +function radioAccessor(scope, element) { var domElement = element[0]; return { - get: function(){ return domElement.checked ? domElement.value : null; }, - set: function(value){ domElement.checked = value == domElement.value; } + get: function(){ + return domElement.checked ? domElement.value : null; + }, + set: function(value){ + domElement.checked = value == domElement.value; + } }; } -function optionsAccessor(element) { +function optionsAccessor(scope, element) { var options = element[0].options; return { get: function(){ @@ -107,7 +115,7 @@ function inputWidget(events, modelAccessor, viewAccessor, initValue) { return function(element) { var scope = this, model = modelAccessor(scope, element), - view = viewAccessor(element), + view = viewAccessor(scope, element), action = element.attr('ng-action') || '', value = view.get() || copy(initValue); if (isDefined(value)) model.set(value); diff --git a/src/apis.js b/src/apis.js index e375e8fc..3d0c5db3 100644 --- a/src/apis.js +++ b/src/apis.js @@ -11,11 +11,15 @@ var angularGlobal = { } }; -var angularCollection = {}; +var angularCollection = { + 'size': size +}; var angularObject = {}; var angularArray = { + 'indexOf': indexOf, + 'include': includes, 'includeIf':function(array, value, condition) { - var index = _.indexOf(array, value); + var index = indexOf(array, value); if (condition) { if (index == -1) array.push(value); @@ -36,7 +40,7 @@ var angularArray = { return sum; }, 'remove':function(array, value) { - var index = _.indexOf(array, value); + var index = indexOf(array, value); if (index >=0) array.splice(index, 1); return value; @@ -44,7 +48,7 @@ var angularArray = { 'find':function(array, condition, defaultValue) { if (!condition) return undefined; var fn = angular['Function']['compile'](condition); - _.detect(array, function($){ + foreach(array, function($){ if (fn($)){ defaultValue = $; return true; @@ -65,7 +69,6 @@ var angularArray = { } return true; }; - var getter = Scope.getter; var search = function(obj, text){ if (text.charAt(0) === '!') { return !search(obj, text.substr(1)); @@ -136,13 +139,18 @@ var angularArray = { return filtered; }, 'add':function(array, value) { - array.push(_.isUndefined(value)? {} : value); + array.push(isUndefined(value)? {} : value); return array; }, 'count':function(array, condition) { if (!condition) return array.length; - var fn = angular['Function']['compile'](condition); - return _.reduce(array, 0, function(count, $){return count + (fn($)?1:0);}); + var fn = angular['Function']['compile'](condition), count = 0; + foreach(array, function(value){ + if (fn(value)) { + count ++; + } + }); + return count; }, 'orderBy':function(array, expression, descend) { function reverse(comp, descending) { @@ -161,14 +169,14 @@ var angularArray = { return t1 < t2 ? -1 : 1; } } - expression = _.isArray(expression) ? expression: [expression]; - expression = _.map(expression, function($){ + expression = isArray(expression) ? expression: [expression]; + expression = map(expression, function($){ var descending = false; if (typeof $ == "string" && ($.charAt(0) == '+' || $.charAt(0) == '-')) { descending = $.charAt(0) == '-'; $ = $.substring(1); } - var get = $ ? angular['Function']['compile']($) : _.identity; + var get = $ ? angular['Function']['compile']($) : identity; return reverse(function(a,b){ return compare(get(a),get(b)); }, descending); @@ -180,22 +188,24 @@ var angularArray = { } return 0; }; - return _.clone(array).sort(reverse(comparator, descend)); + return copy(array).sort(reverse(comparator, descend)); }, 'orderByToggle':function(predicate, attribute) { var STRIP = /^([+|-])?(.*)/; var ascending = false; var index = -1; - _.detect(predicate, function($, i){ - if ($ == attribute) { - ascending = true; - index = i; - return true; - } - if (($.charAt(0)=='+'||$.charAt(0)=='-') && $.substring(1) == attribute) { - ascending = $.charAt(0) == '+'; - index = i; - return true; + foreach(predicate, function($, i){ + if (index == -1) { + if ($ == attribute) { + ascending = true; + index = i; + return true; + } + if (($.charAt(0)=='+'||$.charAt(0)=='-') && $.substring(1) == attribute) { + ascending = $.charAt(0) == '+'; + index = i; + return true; + } } }); if (index >= 0) { @@ -281,16 +291,14 @@ var angularDate = { var angularFunction = { 'compile':function(expression) { - if (_.isFunction(expression)){ + if (isFunction(expression)){ return expression; } else if (expression){ - var scope = new Scope(); return function($) { - scope.state = $; - return scope.eval(expression); + return createScope($).$eval(expression); }; } else { - return function($){return $;}; + return identity; } } }; diff --git a/src/jqLite.js b/src/jqLite.js index a5014354..449854d5 100644 --- a/src/jqLite.js +++ b/src/jqLite.js @@ -1,5 +1,4 @@ - -/////////////////////////////////// +////////////////////////////////// //JQLite ////////////////////////////////// @@ -38,18 +37,6 @@ function JQLite(element) { this[0] = element; } - -function jqLiteWrap(element) { - if (typeof element == 'string') { - var div = document.createElement('div'); - div.innerHTML = element; - element = div.childNodes[0]; - } - return element instanceof JQLite ? element : new JQLite(element); -} - -jqLite = jqLite || jqLiteWrap; - JQLite.prototype = { data: function(key, value) { var element = this[0], |
