aboutsummaryrefslogtreecommitdiffstats
path: root/src/Browser.js
diff options
context:
space:
mode:
authorMisko Hevery2011-11-10 12:12:02 -0800
committerMisko Hevery2011-11-14 20:31:17 -0800
commit1cc6bee4ce5d574b84b4e0c2ded3686de7ab71ef (patch)
tree5810a2c8ef2dc7de3d6fcba3af79736f05489160 /src/Browser.js
parenta8aa193c6b3111fa3b22c087b2adc9f66ec45386 (diff)
downloadangular.js-1cc6bee4ce5d574b84b4e0c2ded3686de7ab71ef.tar.bz2
docs(browser): moved and migrate browser removed unneeded files.
Diffstat (limited to 'src/Browser.js')
-rw-r--r--src/Browser.js482
1 files changed, 0 insertions, 482 deletions
diff --git a/src/Browser.js b/src/Browser.js
deleted file mode 100644
index 84d9cd44..00000000
--- a/src/Browser.js
+++ /dev/null
@@ -1,482 +0,0 @@
-'use strict';
-
-//////////////////////////////
-// 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.");
-};
-
-
-/**
- * @ngdoc service
- * @name angular.service.$browser
- * @requires $log
- *
- * @description
- * Constructor for the object exposed as $browser service.
- *
- * This object has two goals:
- *
- * - hide all the global state in the browser caused by the window object
- * - abstract away all the browser specific features and inconsistencies
- *
- * For tests we provide {@link angular.module.NG_MOCK.$browser mock implementation} of the `$browser`
- * service, which can be used for convenient testing of the application without the interaction with
- * the real browser apis.
- */
-/**
- * @param {object} window The global window object.
- * @param {object} document jQuery wrapped document.
- * @param {object} body jQuery wrapped document.body.
- * @param {function()} XHR XMLHttpRequest constructor.
- * @param {object} $log console.log or an object with the same interface.
- * @param {object} $sniffer $sniffer service
- */
-function Browser(window, document, body, XHR, $log, $sniffer) {
- var self = this,
- rawDocument = document[0],
- location = window.location,
- history = window.history,
- setTimeout = window.setTimeout,
- clearTimeout = window.clearTimeout,
- pendingDeferIds = {};
-
- self.isMock = false;
-
- //////////////////////////////////////////////////////////////
- // XHR API
- //////////////////////////////////////////////////////////////
- var idCounter = 0;
- var outstandingRequestCount = 0;
- var outstandingRequestCallbacks = [];
-
-
- /**
- * Executes the `fn` function(supports currying) and decrements the `outstandingRequestCallbacks`
- * counter. If the counter reaches 0, all the `outstandingRequestCallbacks` are executed.
- */
- function completeOutstandingRequest(fn) {
- try {
- fn.apply(null, sliceArgs(arguments, 1));
- } finally {
- outstandingRequestCount--;
- if (outstandingRequestCount === 0) {
- while(outstandingRequestCallbacks.length) {
- try {
- outstandingRequestCallbacks.pop()();
- } catch (e) {
- $log.error(e);
- }
- }
- }
- }
- }
-
- /**
- * @ngdoc method
- * @name angular.service.$browser#xhr
- * @methodOf angular.service.$browser
- *
- * @param {string} method Requested method (get|post|put|delete|head|json)
- * @param {string} url Requested url
- * @param {?string} post Post data to send (null if nothing to post)
- * @param {function(number, string)} callback Function that will be called on response
- * @param {object=} header additional HTTP headers to send with XHR.
- * Standard headers are:
- * <ul>
- * <li><tt>Content-Type</tt>: <tt>application/x-www-form-urlencoded</tt></li>
- * <li><tt>Accept</tt>: <tt>application/json, text/plain, &#42;/&#42;</tt></li>
- * <li><tt>X-Requested-With</tt>: <tt>XMLHttpRequest</tt></li>
- * </ul>
- *
- * @description
- * Send ajax request
- */
- self.xhr = function(method, url, post, callback, headers) {
- outstandingRequestCount ++;
- if (lowercase(method) == 'json') {
- var callbackId = ("angular_" + Math.random() + '_' + (idCounter++)).replace(/\d\./, '');
- window[callbackId] = function(data) {
- window[callbackId].data = data;
- };
-
- var script = self.addJs(url.replace('JSON_CALLBACK', callbackId), function() {
- if (window[callbackId].data) {
- completeOutstandingRequest(callback, 200, window[callbackId].data);
- } else {
- completeOutstandingRequest(callback);
- }
- delete window[callbackId];
- body[0].removeChild(script);
- });
- } else {
- var xhr = new XHR();
- xhr.open(method, url, true);
- forEach(headers, function(value, key) {
- if (value) xhr.setRequestHeader(key, value);
- });
- xhr.onreadystatechange = function() {
- if (xhr.readyState == 4) {
- // normalize IE bug (http://bugs.jquery.com/ticket/1450)
- var status = xhr.status == 1223 ? 204 : xhr.status;
- completeOutstandingRequest(callback, status, xhr.responseText);
- }
- };
- xhr.send(post || '');
- }
- };
-
- /**
- * @private
- * Note: this method is used only by scenario runner
- * TODO(vojta): prefix this method with $$ ?
- * @param {function()} callback Function that will be called when no outstanding request
- */
- self.notifyWhenNoOutstandingRequests = function(callback) {
- // force browser to execute all pollFns - this is needed so that cookies and other pollers fire
- // at some deterministic time in respect to the test runner's actions. Leaving things up to the
- // regular poller would result in flaky tests.
- forEach(pollFns, function(pollFn){ pollFn(); });
-
- if (outstandingRequestCount === 0) {
- callback();
- } else {
- outstandingRequestCallbacks.push(callback);
- }
- };
-
- //////////////////////////////////////////////////////////////
- // Poll Watcher API
- //////////////////////////////////////////////////////////////
- var pollFns = [],
- pollTimeout;
-
- /**
- * @ngdoc method
- * @name angular.service.$browser#addPollFn
- * @methodOf angular.service.$browser
- *
- * @param {function()} fn Poll function to add
- *
- * @description
- * Adds a function to the list of functions that poller periodically executes,
- * and starts polling if not started yet.
- *
- * @returns {function()} the added function
- */
- self.addPollFn = function(fn) {
- if (isUndefined(pollTimeout)) startPoller(100, setTimeout);
- pollFns.push(fn);
- return fn;
- };
-
- /**
- * @param {number} interval How often should browser call poll functions (ms)
- * @param {function()} setTimeout Reference to a real or fake `setTimeout` function.
- *
- * @description
- * Configures the poller to run in the specified intervals, using the specified
- * setTimeout fn and kicks it off.
- */
- function startPoller(interval, setTimeout) {
- (function check() {
- forEach(pollFns, function(pollFn){ pollFn(); });
- pollTimeout = setTimeout(check, interval);
- })();
- }
-
- //////////////////////////////////////////////////////////////
- // URL API
- //////////////////////////////////////////////////////////////
-
- var lastBrowserUrl = location.href;
-
- /**
- * @ngdoc method
- * @name angular.service.$browser#url
- * @methodOf angular.service.$browser
- *
- * @description
- * GETTER:
- * Without any argument, this method just returns current value of location.href.
- *
- * SETTER:
- * With at least one argument, this method sets url to new value.
- * If html5 history api supported, pushState/replaceState is used, otherwise
- * location.href/location.replace is used.
- * Returns its own instance to allow chaining
- *
- * NOTE: this api is intended for use only by the $location service. Please use the
- * {@link angular.service.$location $location service} to change url.
- *
- * @param {string} url New url (when used as setter)
- * @param {boolean=} replace Should new url replace current history record ?
- */
- self.url = function(url, replace) {
- // setter
- if (url) {
- lastBrowserUrl = url;
- if ($sniffer.history) {
- if (replace) history.replaceState(null, '', url);
- else history.pushState(null, '', url);
- } else {
- if (replace) location.replace(url);
- else location.href = url;
- }
- return self;
- // getter
- } else {
- return location.href;
- }
- };
-
- var urlChangeListeners = [],
- urlChangeInit = false;
-
- function fireUrlChange() {
- if (lastBrowserUrl == self.url()) return;
-
- lastBrowserUrl = self.url();
- forEach(urlChangeListeners, function(listener) {
- listener(self.url());
- });
- }
-
- /**
- * @ngdoc method
- * @name angular.service.$browser#onUrlChange
- * @methodOf angular.service.$browser
- * @TODO(vojta): refactor to use node's syntax for events
- *
- * @description
- * Register callback function that will be called, when url changes.
- *
- * It's only called when the url is changed by outside of angular:
- * - user types different url into address bar
- * - user clicks on history (forward/back) button
- * - user clicks on a link
- *
- * It's not called when url is changed by $browser.url() method
- *
- * The listener gets called with new url as parameter.
- *
- * NOTE: this api is intended for use only by the $location service. Please use the
- * {@link angular.service.$location $location service} to monitor url changes in angular apps.
- *
- * @param {function(string)} listener Listener function to be called when url changes.
- * @return {function(string)} Returns the registered listener fn - handy if the fn is anonymous.
- */
- self.onUrlChange = function(callback) {
- if (!urlChangeInit) {
- // We listen on both (hashchange/popstate) when available, as some browsers (e.g. Opera)
- // don't fire popstate when user change the address bar and don't fire hashchange when url
- // changed by push/replaceState
-
- // html5 history api - popstate event
- if ($sniffer.history) jqLite(window).bind('popstate', fireUrlChange);
- // hashchange event
- if ($sniffer.hashchange) jqLite(window).bind('hashchange', fireUrlChange);
- // polling
- else self.addPollFn(fireUrlChange);
-
- urlChangeInit = true;
- }
-
- urlChangeListeners.push(callback);
- return callback;
- };
-
- //////////////////////////////////////////////////////////////
- // Cookies API
- //////////////////////////////////////////////////////////////
- var lastCookies = {};
- var lastCookieString = '';
-
- /**
- * @ngdoc method
- * @name angular.service.$browser#cookies
- * @methodOf angular.service.$browser
- *
- * @param {string=} name Cookie name
- * @param {string=} value Cokkie value
- *
- * @description
- * The cookies method provides a 'private' low level access to browser cookies.
- * It is not meant to be used directly, use the $cookie service instead.
- *
- * The return values vary depending on the arguments that the method was called with as follows:
- * <ul>
- * <li>cookies() -> hash of all cookies, this is NOT a copy of the internal state, so do not modify it</li>
- * <li>cookies(name, value) -> set name to value, if value is undefined delete the cookie</li>
- * <li>cookies(name) -> the same as (name, undefined) == DELETES (no one calls it right now that way)</li>
- * </ul>
- *
- * @returns {Object} Hash of all cookies (if called without any parameter)
- */
- self.cookies = function(name, value) {
- var cookieLength, cookieArray, cookie, i, keyValue, index;
-
- if (name) {
- if (value === undefined) {
- rawDocument.cookie = escape(name) + "=;expires=Thu, 01 Jan 1970 00:00:00 GMT";
- } else {
- if (isString(value)) {
- rawDocument.cookie = escape(name) + '=' + escape(value);
-
- cookieLength = name.length + value.length + 1;
- if (cookieLength > 4096) {
- $log.warn("Cookie '"+ name +"' possibly not set or overflowed because it was too large ("+
- cookieLength + " > 4096 bytes)!");
- }
- if (lastCookies.length > 20) {
- $log.warn("Cookie '"+ name +"' possibly not set or overflowed because too many cookies " +
- "were already set (" + lastCookies.length + " > 20 )");
- }
- }
- }
- } else {
- if (rawDocument.cookie !== lastCookieString) {
- lastCookieString = rawDocument.cookie;
- cookieArray = lastCookieString.split("; ");
- lastCookies = {};
-
- for (i = 0; i < cookieArray.length; i++) {
- cookie = cookieArray[i];
- index = cookie.indexOf('=');
- if (index > 0) { //ignore nameless cookies
- lastCookies[unescape(cookie.substring(0, index))] = unescape(cookie.substring(index + 1));
- }
- }
- }
- return lastCookies;
- }
- };
-
-
- /**
- * @ngdoc method
- * @name angular.service.$browser#defer
- * @methodOf angular.service.$browser
- * @param {function()} fn A function, who's execution should be defered.
- * @param {number=} [delay=0] of milliseconds to defer the function execution.
- * @returns {*} DeferId that can be used to cancel the task via `$browser.defer.cancel()`.
- *
- * @description
- * Executes a fn asynchroniously via `setTimeout(fn, delay)`.
- *
- * Unlike when calling `setTimeout` directly, in test this function is mocked and instead of using
- * `setTimeout` in tests, the fns are queued in an array, which can be programmatically flushed
- * via `$browser.defer.flush()`.
- *
- */
- self.defer = function(fn, delay) {
- var timeoutId;
- outstandingRequestCount++;
- timeoutId = setTimeout(function() {
- delete pendingDeferIds[timeoutId];
- completeOutstandingRequest(fn);
- }, delay || 0);
- pendingDeferIds[timeoutId] = true;
- return timeoutId;
- };
-
-
- /**
- * THIS DOC IS NOT VISIBLE because ngdocs can't process docs for foo#method.method
- *
- * @name angular.service.$browser#defer.cancel
- * @methodOf angular.service.$browser.defer
- *
- * @description
- * Cancels a defered task identified with `deferId`.
- *
- * @param {*} deferId Token returned by the `$browser.defer` function.
- * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfuly canceled.
- */
- self.defer.cancel = function(deferId) {
- if (pendingDeferIds[deferId]) {
- delete pendingDeferIds[deferId];
- clearTimeout(deferId);
- completeOutstandingRequest(noop);
- return true;
- }
- return false;
- };
-
-
- //////////////////////////////////////////////////////////////
- // Misc API
- //////////////////////////////////////////////////////////////
-
- /**
- * @ngdoc method
- * @name angular.service.$browser#addCss
- * @methodOf angular.service.$browser
- *
- * @param {string} url Url to css file
- * @description
- * Adds a stylesheet tag to the head.
- */
- self.addCss = function(url) {
- var link = jqLite(rawDocument.createElement('link'));
- link.attr('rel', 'stylesheet');
- link.attr('type', 'text/css');
- link.attr('href', url);
- body.append(link);
- };
-
-
- /**
- * @ngdoc method
- * @name angular.service.$browser#addJs
- * @methodOf angular.service.$browser
- *
- * @param {string} url Url to js file
- *
- * @description
- * Adds a script tag to the head.
- */
- self.addJs = function(url, done) {
- // we can't use jQuery/jqLite here because jQuery does crazy shit with script elements, e.g.:
- // - fetches local scripts via XHR and evals them
- // - adds and immediately removes script elements from the document
- var script = rawDocument.createElement('script');
-
- script.type = 'text/javascript';
- script.src = url;
-
- if (msie) {
- script.onreadystatechange = function() {
- /loaded|complete/.test(script.readyState) && done && done();
- };
- } else {
- if (done) script.onload = script.onerror = done;
- }
-
- body[0].appendChild(script);
-
- return script;
- };
-
- /**
- * Returns current <base href>
- * (always relative - without domain)
- *
- * @returns {string=}
- */
- self.baseHref = function() {
- var href = document.find('base').attr('href');
- return href ? href.replace(/^https?\:\/\/[^\/]*/, '') : href;
- };
-}
-
-function $BrowserProvider(){
- this.$get = ['$window', '$log', '$sniffer', '$document',
- function( $window, $log, $sniffer, $document){
- return new Browser($window, $document, $document.find('body'), XHR, $log, $sniffer);
- }];
-}