diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/Angular.js | 1 | ||||
| -rw-r--r-- | src/AngularPublic.js | 6 | ||||
| -rw-r--r-- | src/Browser.js | 261 | ||||
| -rw-r--r-- | src/services.js | 23 |
4 files changed, 133 insertions, 158 deletions
diff --git a/src/Angular.js b/src/Angular.js index ef1187f2..e3d33c73 100644 --- a/src/Angular.js +++ b/src/Angular.js @@ -35,6 +35,7 @@ var _undefined = undefined, msie = !!/(msie) ([\w.]+)/.exec(lowercase(navigator.userAgent)), jqLite = jQuery || jqLiteWrap, slice = Array.prototype.slice, + push = Array.prototype.push, error = window[$console] ? bind(window[$console], window[$console]['error'] || noop) : noop, angular = window[$angular] || (window[$angular] = {}), angularTextMarkup = extensionMap(angular, 'markup'), diff --git a/src/AngularPublic.js b/src/AngularPublic.js index e9f20b59..40425b8d 100644 --- a/src/AngularPublic.js +++ b/src/AngularPublic.js @@ -4,9 +4,9 @@ angularService('$browser', function browserFactory(){ browserSingleton = new Browser( window.location, jqLite(window.document), - jqLite(window.document.getElementsByTagName('head')[0])); - browserSingleton.startUrlWatcher(); - browserSingleton.startCookieWatcher(); + jqLite(window.document.getElementsByTagName('head')[0]), + XHR); + browserSingleton.startPoller(50, function(delay, fn){setTimeout(delay,fn);}); browserSingleton.bind(); } return browserSingleton; diff --git a/src/Browser.js b/src/Browser.js index 0dacf3c4..e21e419b 100644 --- a/src/Browser.js +++ b/src/Browser.js @@ -1,45 +1,118 @@ ////////////////////////////// // Browser ////////////////////////////// +var XHR = window.XMLHttpRequest || function () { + try { return new ActiveXObject("Msxml2.XMLHTTP.6.0"); } catch (e1) {} + try { return new ActiveXObject("Msxml2.XMLHTTP.3.0"); } catch (e2) {} + try { return new ActiveXObject("Msxml2.XMLHTTP"); } catch (e3) {} + throw new Error("This browser does not support XMLHttpRequest."); +}; -function Browser(location, document, head) { - this.delay = 50; - this.expectedUrl = location.href; - this.urlListeners = []; - this.hoverListener = noop; - this.isMock = false; - this.outstandingRequests = { count: 0, callbacks:[]}; +function Browser(location, document, head, XHR) { + var self = this; + self.isMock = false; - this.XHR = window.XMLHttpRequest || function () { - try { return new ActiveXObject("Msxml2.XMLHTTP.6.0"); } catch (e1) {} - try { return new ActiveXObject("Msxml2.XMLHTTP.3.0"); } catch (e2) {} - try { return new ActiveXObject("Msxml2.XMLHTTP"); } catch (e3) {} - throw new Error("This browser does not support XMLHttpRequest."); - }; - this.setTimeout = function(fn, delay) { - window.setTimeout(fn, delay); + ////////////////////////////////////////////////////////////// + // XHR API + ////////////////////////////////////////////////////////////// + var idCounter = 0; + var outstandingRequestCount = 0; + var outstandingRequestCallbacks = []; + + self.xhr = function(method, url, post, callback){ + if (isFunction(post)) { + callback = post; + post = _null; + } + if (lowercase(method) == 'json') { + var callbackId = "angular_" + Math.random() + '_' + (idCounter++); + callbackId = callbackId.replace(/\d\./, ''); + var script = document[0].createElement('script'); + script.type = 'text/javascript'; + script.src = url.replace('JSON_CALLBACK', callbackId); + head.append(script); + window[callbackId] = function(data){ + window[callbackId] = _undefined; + callback(200, data); + }; + } else { + var xhr = new XHR(); + 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"); + outstandingRequestCount ++; + xhr.onreadystatechange = function() { + if (xhr.readyState == 4) { + try { + callback(xhr.status || 200, xhr.responseText); + } finally { + outstandingRequestCount--; + if (outstandingRequestCount === 0) { + while(outstandingRequestCallbacks.length) { + try { + outstandingRequestCallbacks.pop()(); + } catch (e) { + } + } + } + } + } + }; + xhr.send(post || ''); + } }; - this.location = location; - this.document = document; - var rawDocument = document[0]; - this.head = head; - this.idCounter = 0; + self.notifyWhenNoOutstandingRequests = function(callback){ + if (outstandingRequestCount === 0) { + callback(); + } else { + outstandingRequestCallbacks.push(callback); + } + }; - this.cookies = cookies; - this.watchCookies = function(fn){ cookieListeners.push(fn); }; + ////////////////////////////////////////////////////////////// + // Poll Watcher API + ////////////////////////////////////////////////////////////// + var pollFns = []; + function poll(){ + foreach(pollFns, function(pollFn){ pollFn(); }); + } + self.poll = poll; + self.addPollFn = bind(pollFns, push); + self.startPoller = function(interval, setTimeout){ + (function check(){ + poll(); + setTimeout(check, interval); + })(); + }; - // functions + ////////////////////////////////////////////////////////////// + // URL API + ////////////////////////////////////////////////////////////// + self.setUrl = function(url) { + var existingURL = location.href; + if (!existingURL.match(/#/)) existingURL += '#'; + if (!url.match(/#/)) url += '#'; + location.href = url; + }; + self.getUrl = function() { + return location.href; + }; + + ////////////////////////////////////////////////////////////// + // Cookies API + ////////////////////////////////////////////////////////////// + var rawDocument = document[0]; var lastCookies = {}; var lastCookieString = ''; - var cookieListeners = []; /** * cookies() -> hash of all cookies * cookies(name, value) -> set name to value * if value is undefined delete it * cookies(name) -> should get value, but deletes (no one calls it right now that way) */ - function cookies(name, value){ + self.cookies = function (name, value){ if (name) { if (value === _undefined) { delete lastCookies[name]; @@ -59,139 +132,33 @@ function Browser(location, document, head) { lastCookies[unescape(keyValue[0])] = unescape(keyValue[1]); } } - foreach(cookieListeners, function(fn){ - fn(lastCookies); - }); } return lastCookies; } - } -} - -Browser.prototype = { + }; - bind: function() { - var self = this; - self.document.bind("mouseover", function(event){ - self.hoverListener(jqLite(msie ? event.srcElement : event.target), true); + ////////////////////////////////////////////////////////////// + // Misc API + ////////////////////////////////////////////////////////////// + var hoverListener = noop; + self.hover = function(listener) { hoverListener = listener; }; + self.bind = function() { + document.bind("mouseover", function(event){ + hoverListener(jqLite(msie ? event.srcElement : event.target), true); return true; }); - self.document.bind("mouseleave mouseout click dblclick keypress keyup", function(event){ - self.hoverListener(jqLite(event.target), false); + document.bind("mouseleave mouseout click dblclick keypress keyup", function(event){ + hoverListener(jqLite(event.target), false); return true; }); - }, + }; - hover: function(hoverListener) { - this.hoverListener = hoverListener; - }, - addCss: function(url) { - var doc = this.document[0], - head = jqLite(doc.getElementsByTagName('head')[0]), - link = jqLite(doc.createElement('link')); + self.addCss = function(url) { + var link = jqLite(rawDocument.createElement('link')); link.attr('rel', 'stylesheet'); link.attr('type', 'text/css'); link.attr('href', url); head.append(link); - }, - - xhr: function(method, url, post, callback){ - if (isFunction(post)) { - callback = post; - post = _null; - } - if (lowercase(method) == 'json') { - var callbackId = "angular_" + Math.random() + '_' + (this.idCounter++); - callbackId = callbackId.replace(/\d\./, ''); - var script = this.document[0].createElement('script'); - script.type = 'text/javascript'; - script.src = url.replace('JSON_CALLBACK', callbackId); - this.head.append(script); - window[callbackId] = function(data){ - window[callbackId] = _undefined; - callback(200, data); - }; - } else { - 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) { - try { - callback(xhr.status || 200, xhr.responseText); - } finally { - self.outstandingRequests.count--; - self.processRequestCallbacks(); - } - } - }; - xhr.send(post || ''); - } - }, - - processRequestCallbacks: function(){ - if (this.outstandingRequests.count === 0) { - while(this.outstandingRequests.callbacks.length) { - try { - this.outstandingRequests.callbacks.pop()(); - } catch (e) { - } - } - } - }, - - notifyWhenNoOutstandingRequests: function(callback){ - if (this.outstandingRequests.count === 0) { - callback(); - } else { - this.outstandingRequests.callbacks.push(callback); - } - }, - - watchUrl: function(fn){ - this.urlListeners.push(fn); - }, - - startUrlWatcher: function() { - var self = this; - (function pull () { - if (self.expectedUrl !== self.location.href) { - foreach(self.urlListeners, function(listener){ - try { - listener(self.location.href); - } catch (e) { - error(e); - } - }); - self.expectedUrl = self.location.href; - } - self.setTimeout(pull, self.delay); - })(); - }, - - startCookieWatcher: function() { - var self = this; - (function poll() { - self.cookies(); - self.setTimeout(poll, self.delay); - })(); - }, - - setUrl: function(url) { - var existingURL = this.location.href; - if (!existingURL.match(/#/)) existingURL += '#'; - if (!url.match(/#/)) url += '#'; - if (existingURL != url) { - this.location.href = this.expectedUrl = url; - } - }, - - getUrl: function() { - return this.location.href; - } -}; + }; +} diff --git a/src/services.js b/src/services.js index a84a55db..a0317f20 100644 --- a/src/services.js +++ b/src/services.js @@ -11,14 +11,17 @@ angularService("$location", function(browser){ var scope = this, location = {parse:parseUrl, toString:toString, update:update}, lastLocation = {}; + var lastBrowserUrl = browser.getUrl(); - browser.watchUrl(function(url){ - update(url); - scope.$root.$eval(); + browser.addPollFn(function(){ + if (lastBrowserUrl !== browser.getUrl()) { + update(lastBrowserUrl = browser.getUrl()); + scope.$eval(); + } }); this.$onEval(PRIORITY_FIRST, update); this.$onEval(PRIORITY_LAST, update); - update(browser.getUrl()); + update(lastBrowserUrl); return location; function update(href){ @@ -395,10 +398,14 @@ angularService('$resource', function($xhr){ angularService('$cookies', function($browser) { - var cookies = {}, rootScope = this; - $browser.watchCookies(function(newCookies){ - copy(newCookies, cookies); - rootScope.$eval(); + var cookies = {}, rootScope = this, lastCookies; + $browser.addPollFn(function(){ + var currentCookies = $browser.cookies(); + if (lastCookies != currentCookies) { + lastCookies = currentCookies; + copy(currentCookies, cookies); + rootScope.$eval(); + } }); this.$onEval(PRIORITY_FIRST, update); this.$onEval(PRIORITY_LAST, update); |
