From 85f13d602e31424b2e2d18172872f14a24c31135 Mon Sep 17 00:00:00 2001 From: Misko Hevery Date: Thu, 1 Apr 2010 14:10:28 -0700 Subject: work on $location and autobind --- scenario/widgets.html | 4 +-- src/Angular.js | 19 ++++++++++++- src/angular-bootstrap.js | 39 ++++++++++---------------- src/delete/Model.js | 65 +++++++++++++++++++++++++++++++++++++++++++ src/markups.js | 1 + src/moveToAngularCom/Model.js | 65 ------------------------------------------- src/services.js | 40 +++++++++++++------------- test/BinderTest.js | 4 +-- test/servicesSpec.js | 15 +++++++--- 9 files changed, 133 insertions(+), 119 deletions(-) create mode 100644 src/delete/Model.js delete mode 100644 src/moveToAngularCom/Model.js diff --git a/scenario/widgets.html b/scenario/widgets.html index 21060ebf..5c11a2ee 100644 --- a/scenario/widgets.html +++ b/scenario/widgets.html @@ -2,9 +2,9 @@ - + - + diff --git a/src/Angular.js b/src/Angular.js index 72ff26b0..5b5aa87b 100644 --- a/src/Angular.js +++ b/src/Angular.js @@ -45,7 +45,7 @@ UrlWatcher.prototype = { } }; - +//////////////////////////////////// if (typeof document.getAttribute == 'undefined') document.getAttribute = function() {}; @@ -386,3 +386,20 @@ function compile(element, config) { } ///////////////////////////////////////////////// +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 angularInit(config){ + if (config.autobind) { + compile(window.document, config).$init(); + } +} diff --git a/src/angular-bootstrap.js b/src/angular-bootstrap.js index 7798afa5..b0a3aa4f 100644 --- a/src/angular-bootstrap.js +++ b/src/angular-bootstrap.js @@ -22,23 +22,16 @@ * THE SOFTWARE. */ (function(previousOnLoad){ - var filename = /(.*)\/angular-(.*).js(#(.*))?/; - var scripts = document.getElementsByTagName("SCRIPT"); - var serverPath; - var config = {}; + var filename = /(.*)\/angular-(.*).js(#(.*))?/, + scripts = document.getElementsByTagName("SCRIPT"), + serverPath, + config, + match; for(var j = 0; j < scripts.length; j++) { - var match = (scripts[j].src || "").match(filename); + match = (scripts[j].src || "").match(filename); if (match) { serverPath = match[1]; - parseConfig(match[4]); - } - } - - function parseConfig(args) { - var keyValues = args.split('&'), keyValue, i = 0; - for (; i < keyValues.length; i++) { - keyValue = keyValues[i].split('='); - config[keyValue[0]] = keyValue[1] || true; + config = match[4]; } } @@ -53,7 +46,6 @@ addScript("/jqlite.js"); addScript("/Parser.js"); addScript("/Resource.js"); - addScript("/URLWatcher.js"); // Extension points addScript("/apis.js"); @@ -63,17 +55,14 @@ addScript("/directives.js"); addScript("/markups.js"); addScript("/widgets.js"); + addScript("/services.js"); - if (config.autobind) { - window.onload = function(){ - try { - if (previousOnLoad) previousOnLoad(); - } catch(e) {} - var scope = angular.compile(window.document, config); - if (config.rootScope) window[config.rootScope] = scope; - scope.$init(); - }; - } + window.onload = function(){ + try { + if (previousOnLoad) previousOnLoad(); + } catch(e) {} + angularInit(parseKeyValue(config)); + }; })(window.onload); diff --git a/src/delete/Model.js b/src/delete/Model.js new file mode 100644 index 00000000..b09efd0e --- /dev/null +++ b/src/delete/Model.js @@ -0,0 +1,65 @@ +// Single $ is special and does not get searched +// Double $$ is special an is client only (does not get sent to server) + +function Model(entity, initial) { + this['$$entity'] = entity; + this['$loadFrom'](initial||{}); + this['$entity'] = entity['title']; + this['$migrate'](); +}; + +Model.copyDirectFields = function(src, dst) { + if (src === dst || !src || !dst) return; + var isDataField = function(src, dst, field) { + return (field.substring(0,2) !== '$$') && + (typeof src[field] !== 'function') && + (typeof dst[field] !== 'function'); + }; + for (var field in dst) { + if (isDataField(src, dst, field)) + delete dst[field]; + } + for (field in src) { + if (isDataField(src, dst, field)) + dst[field] = src[field]; + } +}; + +extend(Model.prototype, { + '$migrate': function() { + merge(this['$$entity']['defaults'], this); + return this; + }, + + '$merge': function(other) { + merge(other, this); + return this; + }, + + '$save': function(callback) { + this['$$entity'].datastore.save(this, callback === true ? undefined : callback); + if (callback === true) this['$$entity'].datastore.flush(); + return this; + }, + + '$delete': function(callback) { + this['$$entity'].datastore.remove(this, callback === true ? undefined : callback); + if (callback === true) this['$$entity'].datastore.flush(); + return this; + }, + + '$loadById': function(id, callback) { + this['$$entity'].datastore.load(this, id, callback); + return this; + }, + + '$loadFrom': function(other) { + Model.copyDirectFields(other, this); + return this; + }, + + '$saveTo': function(other) { + Model.copyDirectFields(this, other); + return this; + } +}); \ No newline at end of file diff --git a/src/markups.js b/src/markups.js index 6bc27c85..3ae713fb 100644 --- a/src/markups.js +++ b/src/markups.js @@ -51,6 +51,7 @@ angularTextMarkup('{{}}', function(text, textNode, parentElement) { } }); +// TODO: this should be widget not a markup angularTextMarkup('OPTION', function(text, textNode, parentElement){ if (parentElement[0].nodeName == "OPTION") { var select = document.createElement('select'); diff --git a/src/moveToAngularCom/Model.js b/src/moveToAngularCom/Model.js deleted file mode 100644 index b09efd0e..00000000 --- a/src/moveToAngularCom/Model.js +++ /dev/null @@ -1,65 +0,0 @@ -// Single $ is special and does not get searched -// Double $$ is special an is client only (does not get sent to server) - -function Model(entity, initial) { - this['$$entity'] = entity; - this['$loadFrom'](initial||{}); - this['$entity'] = entity['title']; - this['$migrate'](); -}; - -Model.copyDirectFields = function(src, dst) { - if (src === dst || !src || !dst) return; - var isDataField = function(src, dst, field) { - return (field.substring(0,2) !== '$$') && - (typeof src[field] !== 'function') && - (typeof dst[field] !== 'function'); - }; - for (var field in dst) { - if (isDataField(src, dst, field)) - delete dst[field]; - } - for (field in src) { - if (isDataField(src, dst, field)) - dst[field] = src[field]; - } -}; - -extend(Model.prototype, { - '$migrate': function() { - merge(this['$$entity']['defaults'], this); - return this; - }, - - '$merge': function(other) { - merge(other, this); - return this; - }, - - '$save': function(callback) { - this['$$entity'].datastore.save(this, callback === true ? undefined : callback); - if (callback === true) this['$$entity'].datastore.flush(); - return this; - }, - - '$delete': function(callback) { - this['$$entity'].datastore.remove(this, callback === true ? undefined : callback); - if (callback === true) this['$$entity'].datastore.flush(); - return this; - }, - - '$loadById': function(id, callback) { - this['$$entity'].datastore.load(this, id, callback); - return this; - }, - - '$loadFrom': function(other) { - Model.copyDirectFields(other, this); - return this; - }, - - '$saveTo': function(other) { - Model.copyDirectFields(this, other); - return this; - } -}); \ No newline at end of file diff --git a/src/services.js b/src/services.js index 14c71363..5d235b32 100644 --- a/src/services.js +++ b/src/services.js @@ -1,34 +1,34 @@ angularService("$window", bind(window, identity, window)); -angularService("$anchor", function(){ +var URL_MATCH = /^(file|ftp|http|https):\/\/(\w+:{0,1}\w*@)?([\w\.]+)(:([0-9]+))?([^\?#]+)?(\?([^#]*))((#([^\?]*))(\?([^\?]*))?)$/; +angularService("$location", function(){ var scope = this; - function anchor(url){ + function location(url){ if (isDefined(url)) { - if (url.charAt(0) == '#') url = url.substr(1); - var pathQuery = url.split('?'); - anchor.path = decodeURIComponent(pathQuery[0]); - anchor.param = {}; - foreach((pathQuery[1] || "").split('&'), function(keyValue){ - if (keyValue) { - var parts = keyValue.split('='); - var key = decodeURIComponent(parts[0]); - var value = parts[1]; - if (!value) value = true; - anchor.param[key] = decodeURIComponent(value); - } - }); + var match = URL_MATCH.exec(url); + dump(match); + location.href = url; + location.protocol = match[1]; + location.host = match[3]; + location.port = match[5]; + location.path = match[6]; + location.search = parseKeyValue(match[8]); + location.hash = match[9]; + location.hashPath = match[11]; + location.hashSearch = parseKeyValue(match[13]); + foreach(location, dump); } var params = []; - foreach(anchor.param, function(value, key){ + foreach(location.param, function(value, key){ params.push(encodeURIComponent(key) + '=' + encodeURIComponent(value)); }); - return (anchor.path ? anchor.path : '') + (params.length ? '?' + params.join('&') : ''); + return (location.path ? location.path : '') + (params.length ? '?' + params.join('&') : ''); }; this.$config.location.watch(function(url){ - anchor(url); + location(url); }); this.$onEval(PRIORITY_LAST, function(){ - scope.$config.location.set(anchor()); + scope.$config.location.set(location()); }); - return anchor; + return location; }); diff --git a/test/BinderTest.js b/test/BinderTest.js index 67800e62..9c5c5dc6 100644 --- a/test/BinderTest.js +++ b/test/BinderTest.js @@ -721,13 +721,13 @@ BinderTest.prototype.testItShouldSelectTheCorrectRadioBox = function() { var male = jqLite(c.node[0].childNodes[1]); female.click(); - assertEquals("female", c.scope.$get("sex")); + assertEquals("female", c.scope.sex); assertEquals(true, female[0].checked); assertEquals(false, male[0].checked); assertEquals("female", female.val()); male.click(); - assertEquals("male", c.scope.$get("sex")); + assertEquals("male", c.scope.sex); assertEquals(false, female[0].checked); assertEquals(true, male[0].checked); assertEquals("male", male.val()); diff --git a/test/servicesSpec.js b/test/servicesSpec.js index 5a6bcedc..88cbc947 100644 --- a/test/servicesSpec.js +++ b/test/servicesSpec.js @@ -13,10 +13,17 @@ describe("services", function(){ expect(scope.$window).toEqual(window); }); - it("should inject $anchor", function(){ - scope.$anchor('#path?key=value'); - expect(scope.$anchor.path).toEqual("path"); - expect(scope.$anchor.param).toEqual({key:'value'}); + it("should inject $location", function(){ + scope.$location('http://host:1234/p/a/t/h?query=value#path?key=value'); + expect(scope.$location.href).toEqual("http://host:123/p/a/t/h?query=value#path?key=value"); + expect(scope.$location.protocol).toEqual("http"); + expect(scope.$location.host).toEqual("host"); + expect(scope.$location.port).toEqual("1234"); + expect(scope.$location.path).toEqual("/p/a/t/h"); + expect(scope.$location.search).toEqual({query:'value'}); + expect(scope.$location.hash).toEqual('path?key=value'); + expect(scope.$location.hashPath).toEqual('path'); + expect(scope.$location.hashSearch).toEqual({key:'value'}); scope.$anchor.path = 'page=http://path'; scope.$anchor.param = {k:'a=b'}; -- cgit v1.2.3
Description