diff options
| author | Misko Hevery | 2010-01-23 15:54:58 -0800 |
|---|---|---|
| committer | Misko Hevery | 2010-01-23 15:54:58 -0800 |
| commit | 4460328bc1173f5d97fb4ff54edc041968486fce (patch) | |
| tree | 40e18a175f7f1ae104aa56347fe5038526374ed8 /src | |
| parent | e41ee88ef85986dcd0fea23fefcc57d89cee5c0b (diff) | |
| download | angular.js-4460328bc1173f5d97fb4ff54edc041968486fce.tar.bz2 | |
lots of cleanup to get it ready for OS
Diffstat (limited to 'src')
| -rw-r--r-- | src/Angular.js | 328 | ||||
| -rw-r--r-- | src/Binder.js | 19 | ||||
| -rw-r--r-- | src/JSON.js | 18 | ||||
| -rw-r--r-- | src/Users.js | 4 | ||||
| -rw-r--r-- | src/Widgets.js | 11 |
5 files changed, 163 insertions, 217 deletions
diff --git a/src/Angular.js b/src/Angular.js index 3dc72ff7..51fca458 100644 --- a/src/Angular.js +++ b/src/Angular.js @@ -134,16 +134,6 @@ function bind(_this, _function) { }; } -function shiftBind(_this, _function) { - return function() { - var args = [ this ]; - for ( var i = 0; i < arguments.length; i++) { - args.push(arguments[i]); - } - return _function.apply(_this, args); - }; -} - function outerHTML(node) { var temp = document.createElement('div'); temp.appendChild(node); @@ -177,159 +167,9 @@ function merge(src, dst) { } // //////////////////////////// -// Angular +// UrlWatcher // //////////////////////////// -function Angular(document, head, config) { - this.document = jQuery(document); - this.head = jQuery(head); - this.config = config; - this.location = window.location; -} - -Angular.prototype = { - load: function() { - this.configureLogging(); - log("Server: " + this.config.server); - this.configureJQueryPlugins(); - this.computeConfiguration(); - this.bindHtml(); - }, - - configureJQueryPlugins: function() { - log('Angular.configureJQueryPlugins()'); - jQuery['fn']['scope'] = function() { - var element = this; - while (element && element.get(0)) { - var scope = element.data("scope"); - if (scope) - return scope; - element = element.parent(); - } - return null; - }; - jQuery['fn']['controller'] = function() { - return this.data('controller') || NullController.instance; - }; - }, - - uid: function() { - return "" + new Date().getTime(); - }, - - computeConfiguration: function() { - var config = this.config; - if (!config.database) { - var match = config.server.match(/https?:\/\/([\w]*)/); - config.database = match ? match[1] : "$MEMORY"; - } - }, - - bindHtml: function() { - log('Angular.bindHtml()'); - var watcher = this.watcher = new UrlWatcher(this.location); - var document = this.document; - var widgetFactory = new WidgetFactory(this.config.server, this.config.database); - var binder = new Binder(document[0], widgetFactory, watcher, this.config); - widgetFactory.onChangeListener = shiftBind(binder, binder.updateModel); - var controlBar = new ControlBar(document.find('body'), this.config.server); - var onUpdate = function(){binder.updateView();}; - var server = this.config.database=="$MEMORY" ? - new FrameServer(this.window) : - new Server(this.config.server, jQuery.getScript); - server = new VisualServer(server, new Status(jQuery(document.body)), onUpdate); - var users = new Users(server, controlBar); - var databasePath = '/data/' + this.config.database; - var post = function(request, callback){ - server.request("POST", databasePath, request, callback); - }; - var datastore = new DataStore(post, users, binder.anchor); - binder.updateListeners.push(function(){datastore.flush();}); - var scope = new Scope( { - '$anchor' : binder.anchor, - '$binder' : binder, - '$config' : this.config, - '$console' : window.console, - '$datastore' : datastore, - '$save' : function(callback) { - datastore.saveScope(scope.state, callback, binder.anchor); - }, - '$window' : window, - '$uid' : this.uid, - '$users' : users - }, "ROOT"); - - document.data('scope', scope); - log('$binder.entity()'); - binder.entity(scope); - - log('$binder.compile()'); - binder.compile(); - - log('ControlBar.bind()'); - controlBar.bind(); - - log('$users.fetchCurrentUser()'); - function fetchCurrentUser() { - users.fetchCurrentUser(function(u) { - if (!u && document.find("[ng-auth=eager]").length) { - users.login(); - } - }); - } - fetchCurrentUser(); - - log('PopUp.bind()'); - new PopUp(document).bind(); - - log('$binder.parseAnchor()'); - binder.parseAnchor(); - - document.find("body").show(); - log('ready()'); - }, - - visualPost: function(delegate) { - var status = new Status(jQuery(document.body)); - return function(request, delegateCallback) { - status.beginRequest(request); - var callback = function() { - status.endRequest(); - try { - delegateCallback.apply(this, arguments); - } catch (e) { - alert(toJson(e)); - } - }; - delegate(request, callback); - }; - }, - - configureLogging: function() { - var url = window.location.href + '#'; - url = url.split('#')[1]; - var config = { - debug : null - }; - var configs = url.split('&'); - for ( var i = 0; i < configs.length; i++) { - var part = (configs[i] + '=').split('='); - config[part[0]] = part[1]; - } - if (config.debug == 'console') { - consoleNode = document.createElement("div"); - consoleNode.id = 'ng-console'; - document.getElementsByTagName('body')[0].appendChild(consoleNode); - log = function() { - consoleLog('ng-console-info', arguments); - }; - console.error = function() { - consoleLog('ng-console-error', arguments); - }; - } - } -}; - function UrlWatcher(location) { this.location = location; this.delay = 25; @@ -343,6 +183,9 @@ function UrlWatcher(location) { } UrlWatcher.prototype = { + listen: function(fn){ + this.listener = fn; + }, watch: function() { var self = this; var pull = function() { @@ -369,48 +212,149 @@ UrlWatcher.prototype = { self.setTimeout(pull, self.delay); }; pull(); + return this; }, - setUrl: function(url) { - //TODO: conditionaly? - var existingURL = window.location.href; + set: function(url) { + var existingURL = this.location.href; if (!existingURL.match(/#/)) existingURL += '#'; if (existingURL != url) - window.location.href = url; + this.location.href = url; this.existingURL = url; }, - getUrl: function() { + get: function() { return window.location.href; } }; - -angular['compile'] = function(root, config) { - config = config || {}; - var defaults = { - 'server': "", - 'addUrlChangeListener': noop - }; - //todo: don't start watcher - var angular = new Angular(root, jQuery("head"), _(defaults).extend(config)); - //todo: don't load stylesheet by default - // loader.loadCss('/stylesheets/jquery-ui/smoothness/jquery-ui-1.7.1.css'); - // loader.loadCss('/stylesheets/css'); - angular.load(); - var scope = jQuery(root).scope(); - //TODO: cleanup - return { - 'updateView':function(){return scope.updateView();}, - 'set':function(){return scope.set.apply(scope, arguments);}, - 'get':function(){return scope.get.apply(scope, arguments);}, - 'init':function(){scope.get('$binder.executeInit')(); scope.updateView();}, - 'watchUrl':function(){ - var binder = scope.get('$binder'); - var watcher = angular.watcher; - watcher.listener = bind(binder, binder.onUrlChange, watcher); - watcher.onUpdate = function(){alert("update");}; - watcher.watch(); + +///////////////////////////////////////////////// +function configureJQueryPlugins() { + log('Angular.configureJQueryPlugins()'); + var fn = jQuery['fn']; + fn['scope'] = function() { + var element = this; + while (element && element.get(0)) { + var scope = element.data("scope"); + if (scope) + return scope; + element = element.parent(); } + return null; + }; + fn['controller'] = function() { + return this.data('controller') || NullController.instance; }; +} + +function configureLogging(config) { + if (config.debug == 'console' && !consoleNode) { + consoleNode = document.createElement("div"); + consoleNode.id = 'ng-console'; + document.getElementsByTagName('body')[0].appendChild(consoleNode); + log = function() { + consoleLog('ng-console-info', arguments); + }; + console.error = function() { + consoleLog('ng-console-error', arguments); + }; + } +} + +function exposeMethods(obj, methods){ + var bound = {}; + foreach(methods, function(fn, name){ + bound[name] = _(fn).bind(obj); + }); + return bound; +} + +function wireAngular(element, config) { + var widgetFactory = new WidgetFactory(config['server'], config['database']); + var binder = new Binder(element[0], widgetFactory, config['location'], config); + var controlBar = new ControlBar(element.find('body'), config.server); + var onUpdate = function(){binder.updateView();}; + var server = config.database=="$MEMORY" ? + new FrameServer(this.window) : + new Server(config.server, jQuery.getScript); + server = new VisualServer(server, new Status(jQuery(element.body)), onUpdate); + var users = new Users(server, controlBar); + var databasePath = '/data/' + config.database; + var post = function(request, callback){ + server.request("POST", databasePath, request, callback); + }; + var datastore = new DataStore(post, users, binder.anchor); + binder.updateListeners.push(function(){datastore.flush();}); + var scope = new Scope({ + '$anchor' : binder.anchor, + '$updateView': _(binder.updateView).bind(binder), + '$config' : config, + '$console' : window.console, + '$datastore' : exposeMethods(datastore, { + 'load': datastore.load, + 'loadMany': datastore.loadMany, + 'loadOrCreate': datastore.loadOrCreate, + 'loadAll': datastore.loadAll, + 'save': datastore.save, + 'remove': datastore.remove, + 'flush': datastore.flush, + 'query': datastore.query, + 'entity': datastore.entity, + 'entities': datastore.entities, + 'documentCountsByUser': datastore.documentCountsByUser, + 'userDocumentIdsByEntity': datastore.userDocumentIdsByEntity, + 'join': datastore.join + }), + '$save' : function(callback) { + datastore.saveScope(scope.state, callback, binder.anchor); + }, + '$window' : window, + '$uid' : function() { + return "" + new Date().getTime(); + }, + '$users' : users + }, "ROOT"); + + element.data('scope', scope); + binder.entity(scope); + binder.compile(); + controlBar.bind(); + + //TODO: remove this code + new PopUp(element).bind(); + + var self = _(exposeMethods(scope, { + 'updateView': scope.updateView, + 'set': scope.set, + 'get': scope.get, + 'eval': scope.eval + })).extend({ + 'init':function(){ + config['location']['listen'](_(binder.onUrlChange).bind(binder)); + binder.parseAnchor(); + binder.executeInit(); + scope.updateView(); + return self; + }, + 'element':element[0], + 'config':config + }); + return self; +} + +angular['startUrlWatcher'] = function(){ + return new UrlWatcher(window['location']).watch(); +}; + +angular['compile'] = function(element, config) { + config = _({ + 'server': "", + 'location': {'get':noop, 'set':noop, 'listen':noop} + }).extend(config||{}); + + configureLogging(config); + configureJQueryPlugins(); + + return wireAngular(jQuery(element), config); };
\ No newline at end of file diff --git a/src/Binder.js b/src/Binder.js index b687fb77..3fc45a20 100644 --- a/src/Binder.js +++ b/src/Binder.js @@ -1,6 +1,6 @@ -function Binder(doc, widgetFactory, urlWatcher, config) { +function Binder(doc, widgetFactory, location, config) { this.doc = doc; - this.urlWatcher = urlWatcher; + this.location = location; this.anchor = {}; this.widgetFactory = widgetFactory; this.config = config || {}; @@ -48,9 +48,8 @@ Binder.prototype = { return params; }, - parseAnchor: function(url) { - var self = this; - url = url || this.urlWatcher.getUrl(); + parseAnchor: function() { + var self = this, url = this.location.get() || ""; var anchorIndex = url.indexOf('#'); if (anchorIndex < 0) return; @@ -65,13 +64,13 @@ Binder.prototype = { }); }, - onUrlChange: function (url) { - this.parseAnchor(url); + onUrlChange: function() { + this.parseAnchor(); this.updateView(); }, updateAnchor: function() { - var url = this.urlWatcher.getUrl(); + var url = this.location.get(); var anchorIndex = url.indexOf('#'); if (anchorIndex > -1) url = url.substring(0, anchorIndex); @@ -88,7 +87,7 @@ Binder.prototype = { sep = '&'; } } - this.urlWatcher.setUrl(url); + this.location.set(url); return url; }, @@ -154,7 +153,7 @@ Binder.prototype = { jNode.addClass("ng-exception"); jNode.attr('ng-error', toJson(e, true)); } - scope.eval('$binder.updateView()'); + scope.get('$updateView')(); return false; }); }, diff --git a/src/JSON.js b/src/JSON.js index 0c842865..98dfddd2 100644 --- a/src/JSON.js +++ b/src/JSON.js @@ -2,7 +2,7 @@ array = [].constructor; function toJson(obj, pretty){ var buf = []; - toJsonArray(buf, obj, pretty ? "\n " : null); + toJsonArray(buf, obj, pretty ? "\n " : null, _([])); return buf.join(''); }; @@ -25,7 +25,14 @@ function fromJson(json) { angular['toJson'] = toJson; angular['fromJson'] = fromJson; -function toJsonArray(buf, obj, pretty){ +function toJsonArray(buf, obj, pretty, stack){ + if (typeof obj == "object") { + if (stack.include(obj)) { + buf.push("RECURSION"); + return; + } + stack.push(obj); + } var type = typeof obj; if (obj === null) { buf.push("null"); @@ -52,7 +59,7 @@ function toJsonArray(buf, obj, pretty){ if (typeof item == 'function' || typeof item == 'undefined') { buf.push("null"); } else { - toJsonArray(buf, item, pretty); + toJsonArray(buf, item, pretty, stack); } sep = true; } @@ -82,7 +89,7 @@ function toJsonArray(buf, obj, pretty){ } buf.push(angular['String']['quote'](key)); buf.push(":"); - toJsonArray(buf, value, childPretty); + toJsonArray(buf, value, childPretty, stack); comma = true; } } catch (e) { @@ -91,4 +98,7 @@ function toJsonArray(buf, obj, pretty){ buf.push("}"); } } + if (typeof obj == "object") { + stack.pop(); + } }; diff --git a/src/Users.js b/src/Users.js index 47da4f73..79ed3129 100644 --- a/src/Users.js +++ b/src/Users.js @@ -7,7 +7,7 @@ Users.prototype = { 'fetchCurrentUser':function(callback) { var self = this; this.server.request("GET", "/account.json", {}, function(code, response){ - self.current = response.user; + self['current'] = response['user']; callback(response.user); }); }, @@ -15,7 +15,7 @@ Users.prototype = { 'logout': function(callback) { var self = this; this.controlBar.logout(function(){ - delete self.current; + delete self['current']; (callback||noop)(); }); }, diff --git a/src/Widgets.js b/src/Widgets.js index f93f2476..a012adf3 100644 --- a/src/Widgets.js +++ b/src/Widgets.js @@ -9,7 +9,6 @@ function WidgetFactory(serverUrl, database) { alert("ERROR: swfobject not loaded!"); }; } - this.onChangeListener = function(){}; }; WidgetFactory.prototype = { @@ -43,12 +42,12 @@ WidgetFactory.prototype = { throw 'Unknown type: ' + type; } input.data('controller', controller); - var binder = scope.get('$binder'); + var updateView = scope.get('$updateView'); var action = function() { if (controller.updateModel(scope)) { var action = jQuery(controller.view).attr('ng-action') || ""; if (scope.evalWidget(controller, action)) { - binder.updateView(scope); + updateView(scope); } } return bubbleEvent; @@ -74,12 +73,6 @@ WidgetFactory.prototype = { var cntl = new FileController(view, fileInput[0].name, swfNode, this.serverUrl + "/data/" + this.database); jQuery(swfNode).data('controller', cntl); return cntl; - }, - - createTextWidget: function(textInput) { - var controller = new TextController(textInput); - controller.onChange(this.onChangeListener); - return controller; } }; ///////////////////// |
