diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/Angular.js | 52 | ||||
| -rw-r--r-- | src/Browser.js | 3 | ||||
| -rw-r--r-- | src/Compiler.js | 6 | ||||
| -rw-r--r-- | src/Parser.js | 13 | ||||
| -rw-r--r-- | src/angular-bootstrap.js | 6 | ||||
| -rw-r--r-- | src/angular.suffix | 2 | ||||
| -rw-r--r-- | src/directives.js | 4 | ||||
| -rw-r--r-- | src/formatters.js | 1 | ||||
| -rw-r--r-- | src/jqLite.js | 17 | ||||
| -rw-r--r-- | src/services.js | 110 | ||||
| -rw-r--r-- | src/widgets.js | 5 |
11 files changed, 129 insertions, 90 deletions
diff --git a/src/Angular.js b/src/Angular.js index 850fe34c..42e2ce89 100644 --- a/src/Angular.js +++ b/src/Angular.js @@ -18,7 +18,7 @@ var consoleNode, slice = Array.prototype.slice, error = window['console'] ? bind(window['console'], window['console']['error'] || noop) : noop, angular = window['angular'] || (window['angular'] = {}), - angularTextMarkup = extensionMap(angular, 'textMarkup'), + angularTextMarkup = extensionMap(angular, 'markup'), angularAttrMarkup = extensionMap(angular, 'attrMarkup'), angularDirective = extensionMap(angular, 'directive'), angularWidget = extensionMap(angular, 'widget', lowercase), @@ -293,13 +293,18 @@ function escapeAttr(html) { 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))); - }; + if (typeof _function == 'function') { + return curryArgs.length == 0 ? + function() { + return _function.apply(_this, arguments); + } : + function() { + return _function.apply(_this, curryArgs.concat(slice.call(arguments, 0, arguments.length))); + }; + } else { + // in IE, native methods ore not functions and so they can not be bound (but they don't need to be) + return _function; + } } function outerHTML(node) { @@ -347,8 +352,8 @@ function parseKeyValue(keyValue) { 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; + key = unescape(key_value[0]); + obj[key] = key_value[1] ? unescape(key_value[1]) : true; } }); return obj; @@ -357,29 +362,42 @@ function parseKeyValue(keyValue) { function toKeyValue(obj) { var parts = []; foreach(obj, function(value, key){ - parts.push(encodeURIComponent(key) + '=' + encodeURIComponent(value)); + parts.push(escape(key) + '=' + escape(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'); + var scope = compile(window.document, null, {'$config':config}); + if (config.css) + scope.$browser.addCss(config.base_url + config.css); scope.$init(); } } -function angularJsConfig(document) { - var filename = /(.*)\/angular(-(.*))?.js(#(.*))?/, +function angularJsConfig(document, config) { + var filename = /^(.*)\/angular(-([^\/]*))?.js(#(.*))?$/, scripts = document.getElementsByTagName("script"), match; + config = extend({ + base_url: '', + css: '../css/angular.css' + }, config); for(var j = 0; j < scripts.length; j++) { match = (scripts[j].src || "").match(filename); if (match) { - return match[5]; + config.base_url = match[1] + '/'; + extend(config, parseKeyValue(match[5])); + eachAttribute(jqLite(scripts[j]), function(value, name){ + if (/^ng:/.exec(name)) { + name = name.substring(3).replace(/-/g, '_'); + if (name == 'autobind') value = true; + config[name] = value; + } + }); } } - return ""; + return config; } diff --git a/src/Browser.js b/src/Browser.js index 3287cf0e..b4314e2c 100644 --- a/src/Browser.js +++ b/src/Browser.js @@ -74,6 +74,9 @@ Browser.prototype = { var xhr = new this.XHR(), self = this; xhr.open(method, url, true); + xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); + xhr.setRequestHeader("Accept", "application/json, text/plain, */*"); + xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest"); this.outstandingRequests.count ++; xhr.onreadystatechange = function() { if (xhr.readyState == 4) { diff --git a/src/Compiler.js b/src/Compiler.js index bcf1f61a..e09f1876 100644 --- a/src/Compiler.js +++ b/src/Compiler.js @@ -69,8 +69,8 @@ Template.prototype = { /////////////////////////////////// //Compiler ////////////////////////////////// -function Compiler(textMarkup, attrMarkup, directives, widgets){ - this.textMarkup = textMarkup; +function Compiler(markup, attrMarkup, directives, widgets){ + this.markup = markup; this.attrMarkup = attrMarkup; this.directives = directives; this.widgets = widgets; @@ -158,7 +158,7 @@ Compiler.prototype = { // process markup for text nodes only eachTextNode(element, function(textNode){ var text = textNode.text(); - foreach(self.textMarkup, function(markup){ + foreach(self.markup, function(markup){ markup.call(selfApi, text, textNode, element); }); }); diff --git a/src/Parser.js b/src/Parser.js index 5c2307e4..5eb75713 100644 --- a/src/Parser.js +++ b/src/Parser.js @@ -599,14 +599,11 @@ Parser.prototype = { for ( var i = 0; i < argsFn.length; i++) { args.push(argsFn[i](self)); } - var fnPtr = fn(self); - if (typeof fnPtr === 'function') { - return fnPtr.apply(self, args); - } else if (fnPtr === undefined) { - return fnPtr; - } else { - throw "Expression '" + fn.isAssignable + "' is not a function."; - } + var fnPtr = fn(self) || noop; + // IE stupidity! + return fnPtr.apply ? + fnPtr.apply(self, args) : + fnPtr(args[0], args[1], args[2], args[3], args[4]); }; }, diff --git a/src/angular-bootstrap.js b/src/angular-bootstrap.js index 90e1104e..1f03b8a3 100644 --- a/src/angular-bootstrap.js +++ b/src/angular-bootstrap.js @@ -22,16 +22,14 @@ * THE SOFTWARE. */ (function(previousOnLoad){ - var filename = /(.*)\/angular-(.*).js(#(.*))?/, + var filename = /^(.*)\/angular-bootstrap.js(#.*)?$/, scripts = document.getElementsByTagName("SCRIPT"), serverPath, - config, match; for(var j = 0; j < scripts.length; j++) { match = (scripts[j].src || "").match(filename); if (match) { serverPath = match[1]; - config = match[4]; } } @@ -63,7 +61,7 @@ try { if (previousOnLoad) previousOnLoad(); } catch(e) {} - angularInit(parseKeyValue(config)); + angularInit(angularJsConfig(document)); }; })(window.onload); diff --git a/src/angular.suffix b/src/angular.suffix index 36d73df2..7e86c5d5 100644 --- a/src/angular.suffix +++ b/src/angular.suffix @@ -3,7 +3,7 @@ try { if (previousOnLoad) previousOnLoad(); } catch(e) {} - angularInit(parseKeyValue(angularJsConfig(document))); + angularInit(angularJsConfig(document)); }; })(window, document, window.onload); diff --git a/src/directives.js b/src/directives.js index ffe37890..9aadbd11 100644 --- a/src/directives.js +++ b/src/directives.js @@ -199,10 +199,10 @@ angularWidget("@ng:repeat", function(expression, element){ angularDirective("ng:click", function(expression, element){ return function(element){ var self = this; - element.bind('click', function(){ + element.bind('click', function(event){ self.$tryEval(expression, element); self.$root.$eval(); - return false; + event.preventDefault(); }); }; }); diff --git a/src/formatters.js b/src/formatters.js index 40462cf3..ca1ce83e 100644 --- a/src/formatters.js +++ b/src/formatters.js @@ -5,6 +5,7 @@ var NUMBER = /^\s*[-+]?\d*(\.\d*)?\s*$/; extend(angularFormatter, { 'noop':formatter(identity, identity), + 'json':formatter(toJson, fromJson), 'boolean':formatter(toString, toBoolean), 'number':formatter(toString, function(obj){ diff --git a/src/jqLite.js b/src/jqLite.js index cff9ae00..22b3c070 100644 --- a/src/jqLite.js +++ b/src/jqLite.js @@ -104,19 +104,14 @@ JQLite.prototype = { eventHandler = bind[type]; if (!eventHandler) { bind[type] = eventHandler = function(event) { - var bubbleEvent = false; - foreach(eventHandler.fns, function(fn){ - bubbleEvent = bubbleEvent || fn.call(self, event); - }); - if (!bubbleEvent) { - if (msie) { + if (!event.preventDefault) { + event.preventDefault = function(){ event.returnValue = false; - event.cancelBubble = true; - } else { - event.preventDefault(); - event.stopPropagation(); - } + }; } + foreach(eventHandler.fns, function(fn){ + fn.call(self, event); + }); }; eventHandler.fns = []; addEventListener(element, type, eventHandler); diff --git a/src/services.js b/src/services.js index 106f8954..8df23564 100644 --- a/src/services.js +++ b/src/services.js @@ -7,61 +7,87 @@ var URL_MATCH = /^(file|ftp|http|https):\/\/(\w+:{0,1}\w*@)?([\w\.-]*)(:([0-9]+) var HASH_MATCH = /^([^\?]*)?(\?([^\?]*))?$/; var DEFAULT_PORTS = {'http': 80, 'https': 443, 'ftp':21}; angularService("$location", function(browser){ - var scope = this, location = {parse:parseUrl, toString:toString}; - var lastHash, lastUrl; + var scope = this, + location = {parse:parseUrl, toString:toString, update:update}, + lastLocation = {}; + + browser.watchUrl(function(url){ + update(url); + scope.$root.$eval(); + }); + this.$onEval(PRIORITY_FIRST, update); + this.$onEval(PRIORITY_LAST, update); + update(browser.getUrl()); + return location; + + function update(href){ + if (href) { + parseUrl(href); + } else { + href = check('href') || checkProtocol(); + var hash = check('hash'); + if (isUndefined(hash)) hash = checkHashPathSearch(); + if (isDefined(hash)) { + href = (href || location.href).split('#')[0]; + href+= '#' + hash; + } + if (isDefined(href)) { + parseUrl(href); + browser.setUrl(href); + } + } + } + + function check(param) { + return lastLocation[param] == location[param] ? undefined : location[param]; + } + + function checkProtocol(){ + if (lastLocation.protocol === location.protocol && + lastLocation.host === location.host && + lastLocation.port === location.port && + lastLocation.path === location.path && + equals(lastLocation.search, location.search)) + return undefined; + var url = toKeyValue(location.search); + var port = (location.port == DEFAULT_PORTS[location.protocol] ? null : location.port); + return location.protocol + '://' + location.host + + (port ? ':' + port : '') + location.path + + (url ? '?' + url : ''); + } + + function checkHashPathSearch(){ + if (lastLocation.hashPath === location.hashPath && + equals(lastLocation.hashSearch, location.hashSearch) ) + return undefined; + var url = toKeyValue(location.hashSearch); + return escape(location.hashPath) + (url ? '?' + url : ''); + } + function parseUrl(url){ if (isDefined(url)) { var match = URL_MATCH.exec(url); if (match) { - location.href = url; + location.href = url.replace('#$', ''); location.protocol = match[1]; location.host = match[3] || ''; - location.port = match[5] || DEFAULT_PORTS[location.href] || null; + location.port = match[5] || DEFAULT_PORTS[location.protocol] || null; location.path = match[6]; location.search = parseKeyValue(match[8]); - location.hash = match[9] || ''; - if (location.hash) - location.hash = location.hash.substr(1); - parseHash(location.hash); + location.hash = match[10] || ''; + match = HASH_MATCH.exec(location.hash); + location.hashPath = unescape(match[1] || ''); + location.hashSearch = parseKeyValue(match[3]); + + copy(location, lastLocation); } } } - function parseHash(hash) { - var match = HASH_MATCH.exec(hash); - location.hashPath = match[1] || ''; - location.hashSearch = parseKeyValue(match[3]); - lastHash = hash; - } + function toString() { - if (lastHash === location.hash) { - var hashKeyValue = toKeyValue(location.hashSearch), - hash = (location.hashPath ? location.hashPath : '') + (hashKeyValue ? '?' + hashKeyValue : ''), - url = location.href.split('#')[0] + '#' + (hash ? hash : ''); - if (url !== location.href) parseUrl(url); - return url; - } else { - parseUrl(location.href.split('#')[0] + '#' + location.hash); - return toString(); - } + update(); + return location.href; } - browser.watchUrl(function(url){ - parseUrl(url); - scope.$root.$eval(); - }); - parseUrl(browser.getUrl()); - this.$onEval(PRIORITY_FIRST, function(){ - if (location.hash != lastHash) { - parseHash(location.hash); - } - }); - this.$onEval(PRIORITY_LAST, function(){ - var url = toString(); - if (lastUrl != url) { - browser.setUrl(url); - lastUrl = url; - } - }); - return location; }, {inject: ['$browser']}); angularService("$log", function($window){ diff --git a/src/widgets.js b/src/widgets.js index 5f0fcf7c..87a302fa 100644 --- a/src/widgets.js +++ b/src/widgets.js @@ -198,14 +198,15 @@ function inputWidget(events, modelAccessor, viewAccessor, initFn) { this.$eval(element.attr('ng:init')||''); // Don't register a handler if we are a button (noopAccessor) and there is no action if (action || modelAccessor !== noopAccessor) { - element.bind(events, function(){ + element.bind(events, function(event){ model.set(view.get()); lastValue = model.get(); scope.$tryEval(action, element); scope.$root.$eval(); // if we have noop initFn than we are just a button, // therefore we want to prevent default action - return initFn != noop; + if(initFn == noop) + event.preventDefault(); }); } view.set(lastValue = model.get()); |
