- */
-
-angular.mock.$ExceptionHandlerProvider = function() {
- var handler;
-
- /**
- * @ngdoc method
- * @name ngMock.$exceptionHandlerProvider#mode
- * @methodOf ngMock.$exceptionHandlerProvider
- *
- * @description
- * Sets the logging mode.
- *
- * @param {string} mode Mode of operation, defaults to `rethrow`.
- *
- * - `rethrow`: If any errors are are passed into the handler in tests, it typically
- * means that there is a bug in the application or test, so this mock will
- * make these tests fail.
- * - `log`: Sometimes it is desirable to test that an error is thrown, for this case the `log` mode stores an
- * array of errors in `$exceptionHandler.errors`, to allow later assertion of them.
- * See {@link ngMock.$log#assertEmpty assertEmpty()} and
- * {@link ngMock.$log#reset reset()}
- */
- this.mode = function(mode) {
- switch(mode) {
- case 'rethrow':
- handler = function(e) {
- throw e;
- };
- break;
- case 'log':
- var errors = [];
-
- handler = function(e) {
- if (arguments.length == 1) {
- errors.push(e);
- } else {
- errors.push([].slice.call(arguments, 0));
- }
- };
-
- handler.errors = errors;
- break;
- default:
- throw Error("Unknown mode '" + mode + "', only 'log'/'rethrow' modes are allowed!");
- }
- };
-
- this.$get = function() {
- return handler;
- };
-
- this.mode('rethrow');
-};
-
-
-/**
- * @ngdoc service
- * @name ngMock.$log
- *
- * @description
- * Mock implementation of {@link ng.$log} that gathers all logged messages in arrays
- * (one array per logging level). These arrays are exposed as `logs` property of each of the
- * level-specific log function, e.g. for level `error` the array is exposed as `$log.error.logs`.
- *
- */
-angular.mock.$LogProvider = function() {
-
- function concat(array1, array2, index) {
- return array1.concat(Array.prototype.slice.call(array2, index));
- }
-
-
- this.$get = function () {
- var $log = {
- log: function() { $log.log.logs.push(concat([], arguments, 0)); },
- warn: function() { $log.warn.logs.push(concat([], arguments, 0)); },
- info: function() { $log.info.logs.push(concat([], arguments, 0)); },
- error: function() { $log.error.logs.push(concat([], arguments, 0)); }
- };
-
- /**
- * @ngdoc method
- * @name ngMock.$log#reset
- * @methodOf ngMock.$log
- *
- * @description
- * Reset all of the logging arrays to empty.
- */
- $log.reset = function () {
- /**
- * @ngdoc property
- * @name ngMock.$log#log.logs
- * @propertyOf ngMock.$log
- *
- * @description
- * Array of logged messages.
- */
- $log.log.logs = [];
- /**
- * @ngdoc property
- * @name ngMock.$log#warn.logs
- * @propertyOf ngMock.$log
- *
- * @description
- * Array of logged messages.
- */
- $log.warn.logs = [];
- /**
- * @ngdoc property
- * @name ngMock.$log#info.logs
- * @propertyOf ngMock.$log
- *
- * @description
- * Array of logged messages.
- */
- $log.info.logs = [];
- /**
- * @ngdoc property
- * @name ngMock.$log#error.logs
- * @propertyOf ngMock.$log
- *
- * @description
- * Array of logged messages.
- */
- $log.error.logs = [];
- };
-
- /**
- * @ngdoc method
- * @name ngMock.$log#assertEmpty
- * @methodOf ngMock.$log
- *
- * @description
- * Assert that the all of the logging methods have no logged messages. If messages present, an exception is thrown.
- */
- $log.assertEmpty = function() {
- var errors = [];
- angular.forEach(['error', 'warn', 'info', 'log'], function(logLevel) {
- angular.forEach($log[logLevel].logs, function(log) {
- angular.forEach(log, function (logItem) {
- errors.push('MOCK $log (' + logLevel + '): ' + String(logItem) + '\n' + (logItem.stack || ''));
- });
- });
- });
- if (errors.length) {
- errors.unshift("Expected $log to be empty! Either a message was logged unexpectedly, or an expected " +
- "log message was not checked and removed:");
- errors.push('');
- throw new Error(errors.join('\n---------\n'));
- }
- };
-
- $log.reset();
- return $log;
- };
-};
-
-
-(function() {
- var R_ISO8061_STR = /^(\d{4})-?(\d\d)-?(\d\d)(?:T(\d\d)(?:\:?(\d\d)(?:\:?(\d\d)(?:\.(\d{3}))?)?)?(Z|([+-])(\d\d):?(\d\d)))?$/;
-
- function jsonStringToDate(string){
- var match;
- if (match = string.match(R_ISO8061_STR)) {
- var date = new Date(0),
- tzHour = 0,
- tzMin = 0;
- if (match[9]) {
- tzHour = int(match[9] + match[10]);
- tzMin = int(match[9] + match[11]);
- }
- date.setUTCFullYear(int(match[1]), int(match[2]) - 1, int(match[3]));
- date.setUTCHours(int(match[4]||0) - tzHour, int(match[5]||0) - tzMin, int(match[6]||0), int(match[7]||0));
- return date;
- }
- return string;
- }
-
- function int(str) {
- return parseInt(str, 10);
- }
-
- function padNumber(num, digits, trim) {
- var neg = '';
- if (num < 0) {
- neg = '-';
- num = -num;
- }
- num = '' + num;
- while(num.length < digits) num = '0' + num;
- if (trim)
- num = num.substr(num.length - digits);
- return neg + num;
- }
-
-
- /**
- * @ngdoc object
- * @name angular.mock.TzDate
- * @description
- *
- * *NOTE*: this is not an injectable instance, just a globally available mock class of `Date`.
- *
- * Mock of the Date type which has its timezone specified via constructor arg.
- *
- * The main purpose is to create Date-like instances with timezone fixed to the specified timezone
- * offset, so that we can test code that depends on local timezone settings without dependency on
- * the time zone settings of the machine where the code is running.
- *
- * @param {number} offset Offset of the *desired* timezone in hours (fractions will be honored)
- * @param {(number|string)} timestamp Timestamp representing the desired time in *UTC*
- *
- * @example
- * !!!! WARNING !!!!!
- * This is not a complete Date object so only methods that were implemented can be called safely.
- * To make matters worse, TzDate instances inherit stuff from Date via a prototype.
- *
- * We do our best to intercept calls to "unimplemented" methods, but since the list of methods is
- * incomplete we might be missing some non-standard methods. This can result in errors like:
- * "Date.prototype.foo called on incompatible Object".
- *
- *
- *
- */
- angular.mock.TzDate = function (offset, timestamp) {
- var self = new Date(0);
- if (angular.isString(timestamp)) {
- var tsStr = timestamp;
-
- self.origDate = jsonStringToDate(timestamp);
-
- timestamp = self.origDate.getTime();
- if (isNaN(timestamp))
- throw {
- name: "Illegal Argument",
- message: "Arg '" + tsStr + "' passed into TzDate constructor is not a valid date string"
- };
- } else {
- self.origDate = new Date(timestamp);
- }
-
- var localOffset = new Date(timestamp).getTimezoneOffset();
- self.offsetDiff = localOffset*60*1000 - offset*1000*60*60;
- self.date = new Date(timestamp + self.offsetDiff);
-
- self.getTime = function() {
- return self.date.getTime() - self.offsetDiff;
- };
-
- self.toLocaleDateString = function() {
- return self.date.toLocaleDateString();
- };
-
- self.getFullYear = function() {
- return self.date.getFullYear();
- };
-
- self.getMonth = function() {
- return self.date.getMonth();
- };
-
- self.getDate = function() {
- return self.date.getDate();
- };
-
- self.getHours = function() {
- return self.date.getHours();
- };
-
- self.getMinutes = function() {
- return self.date.getMinutes();
- };
-
- self.getSeconds = function() {
- return self.date.getSeconds();
- };
-
- self.getTimezoneOffset = function() {
- return offset * 60;
- };
-
- self.getUTCFullYear = function() {
- return self.origDate.getUTCFullYear();
- };
-
- self.getUTCMonth = function() {
- return self.origDate.getUTCMonth();
- };
-
- self.getUTCDate = function() {
- return self.origDate.getUTCDate();
- };
-
- self.getUTCHours = function() {
- return self.origDate.getUTCHours();
- };
-
- self.getUTCMinutes = function() {
- return self.origDate.getUTCMinutes();
- };
-
- self.getUTCSeconds = function() {
- return self.origDate.getUTCSeconds();
- };
-
- self.getUTCMilliseconds = function() {
- return self.origDate.getUTCMilliseconds();
- };
-
- self.getDay = function() {
- return self.date.getDay();
- };
-
- // provide this method only on browsers that already have it
- if (self.toISOString) {
- self.toISOString = function() {
- return padNumber(self.origDate.getUTCFullYear(), 4) + '-' +
- padNumber(self.origDate.getUTCMonth() + 1, 2) + '-' +
- padNumber(self.origDate.getUTCDate(), 2) + 'T' +
- padNumber(self.origDate.getUTCHours(), 2) + ':' +
- padNumber(self.origDate.getUTCMinutes(), 2) + ':' +
- padNumber(self.origDate.getUTCSeconds(), 2) + '.' +
- padNumber(self.origDate.getUTCMilliseconds(), 3) + 'Z'
- }
- }
-
- //hide all methods not implemented in this mock that the Date prototype exposes
- var unimplementedMethods = ['getMilliseconds', 'getUTCDay',
- 'getYear', 'setDate', 'setFullYear', 'setHours', 'setMilliseconds',
- 'setMinutes', 'setMonth', 'setSeconds', 'setTime', 'setUTCDate', 'setUTCFullYear',
- 'setUTCHours', 'setUTCMilliseconds', 'setUTCMinutes', 'setUTCMonth', 'setUTCSeconds',
- 'setYear', 'toDateString', 'toGMTString', 'toJSON', 'toLocaleFormat', 'toLocaleString',
- 'toLocaleTimeString', 'toSource', 'toString', 'toTimeString', 'toUTCString', 'valueOf'];
-
- angular.forEach(unimplementedMethods, function(methodName) {
- self[methodName] = function() {
- throw Error("Method '" + methodName + "' is not implemented in the TzDate mock");
- };
- });
-
- return self;
- };
-
- //make "tzDateInstance instanceof Date" return true
- angular.mock.TzDate.prototype = Date.prototype;
-})();
-
-
-/**
- * @ngdoc function
- * @name angular.mock.dump
- * @description
- *
- * *NOTE*: this is not an injectable instance, just a globally available function.
- *
- * Method for serializing common angular objects (scope, elements, etc..) into strings, useful for debugging.
- *
- * This method is also available on window, where it can be used to display objects on debug console.
- *
- * @param {*} object - any object to turn into string.
- * @return {string} a serialized string of the argument
- */
-angular.mock.dump = function(object) {
- return serialize(object);
-
- function serialize(object) {
- var out;
-
- if (angular.isElement(object)) {
- object = angular.element(object);
- out = angular.element('');
- angular.forEach(object, function(element) {
- out.append(angular.element(element).clone());
- });
- out = out.html();
- } else if (angular.isArray(object)) {
- out = [];
- angular.forEach(object, function(o) {
- out.push(serialize(o));
- });
- out = '[ ' + out.join(', ') + ' ]';
- } else if (angular.isObject(object)) {
- if (angular.isFunction(object.$eval) && angular.isFunction(object.$apply)) {
- out = serializeScope(object);
- } else if (object instanceof Error) {
- out = object.stack || ('' + object.name + ': ' + object.message);
- } else {
- out = angular.toJson(object, true);
- }
- } else {
- out = String(object);
- }
-
- return out;
- }
-
- function serializeScope(scope, offset) {
- offset = offset || ' ';
- var log = [offset + 'Scope(' + scope.$id + '): {'];
- for ( var key in scope ) {
- if (scope.hasOwnProperty(key) && !key.match(/^(\$|this)/)) {
- log.push(' ' + key + ': ' + angular.toJson(scope[key]));
- }
- }
- var child = scope.$$childHead;
- while(child) {
- log.push(serializeScope(child, offset + ' '));
- child = child.$$nextSibling;
- }
- log.push('}');
- return log.join('\n' + offset);
- }
-};
-
-/**
- * @ngdoc object
- * @name ngMock.$httpBackend
- * @description
- * Fake HTTP backend implementation suitable for unit testing application that use the
- * {@link ng.$http $http service}.
- *
- * *Note*: For fake http backend implementation suitable for end-to-end testing or backend-less
- * development please see {@link ngMockE2E.$httpBackend e2e $httpBackend mock}.
- *
- * During unit testing, we want our unit tests to run quickly and have no external dependencies so
- * we don’t want to send {@link https://developer.mozilla.org/en/xmlhttprequest XHR} or
- * {@link http://en.wikipedia.org/wiki/JSONP JSONP} requests to a real server. All we really need is
- * to verify whether a certain request has been sent or not, or alternatively just let the
- * application make requests, respond with pre-trained responses and assert that the end result is
- * what we expect it to be.
- *
- * This mock implementation can be used to respond with static or dynamic responses via the
- * `expect` and `when` apis and their shortcuts (`expectGET`, `whenPOST`, etc).
- *
- * When an Angular application needs some data from a server, it calls the $http service, which
- * sends the request to a real server using $httpBackend service. With dependency injection, it is
- * easy to inject $httpBackend mock (which has the same API as $httpBackend) and use it to verify
- * the requests and respond with some testing data without sending a request to real server.
- *
- * There are two ways to specify what test data should be returned as http responses by the mock
- * backend when the code under test makes http requests:
- *
- * - `$httpBackend.expect` - specifies a request expectation
- * - `$httpBackend.when` - specifies a backend definition
- *
- *
- * # Request Expectations vs Backend Definitions
- *
- * Request expectations provide a way to make assertions about requests made by the application and
- * to define responses for those requests. The test will fail if the expected requests are not made
- * or they are made in the wrong order.
- *
- * Backend definitions allow you to define a fake backend for your application which doesn't assert
- * if a particular request was made or not, it just returns a trained response if a request is made.
- * The test will pass whether or not the request gets made during testing.
- *
- *
- *
- *
Request expectations
Backend definitions
- *
- *
Syntax
- *
.expect(...).respond(...)
- *
.when(...).respond(...)
- *
- *
- *
Typical usage
- *
strict unit tests
- *
loose (black-box) unit testing
- *
- *
- *
Fulfills multiple requests
- *
NO
- *
YES
- *
- *
- *
Order of requests matters
- *
YES
- *
NO
- *
- *
- *
Request required
- *
YES
- *
NO
- *
- *
- *
Response required
- *
optional (see below)
- *
YES
- *
- *
- *
- * In cases where both backend definitions and request expectations are specified during unit
- * testing, the request expectations are evaluated first.
- *
- * If a request expectation has no response specified, the algorithm will search your backend
- * definitions for an appropriate response.
- *
- * If a request didn't match any expectation or if the expectation doesn't have the response
- * defined, the backend definitions are evaluated in sequential order to see if any of them match
- * the request. The response from the first matched definition is returned.
- *
- *
- * # Flushing HTTP requests
- *
- * The $httpBackend used in production, always responds to requests with responses asynchronously.
- * If we preserved this behavior in unit testing, we'd have to create async unit tests, which are
- * hard to write, follow and maintain. At the same time the testing mock, can't respond
- * synchronously because that would change the execution of the code under test. For this reason the
- * mock $httpBackend has a `flush()` method, which allows the test to explicitly flush pending
- * requests and thus preserving the async api of the backend, while allowing the test to execute
- * synchronously.
- *
- *
- * # Unit testing with mock $httpBackend
- *
- *
- // controller
- function MyController($scope, $http) {
- $http.get('/auth.py').success(function(data) {
- $scope.user = data;
- });
-
- this.saveMessage = function(message) {
- $scope.status = 'Saving...';
- $http.post('/add-msg.py', message).success(function(response) {
- $scope.status = '';
- }).error(function() {
- $scope.status = 'ERROR!';
- });
- };
- }
-
- // testing controller
- var $httpBackend;
-
- beforeEach(inject(function($injector) {
- $httpBackend = $injector.get('$httpBackend');
-
- // backend definition common for all tests
- $httpBackend.when('GET', '/auth.py').respond({userId: 'userX'}, {'A-Token': 'xxx'});
- }));
-
-
- afterEach(function() {
- $httpBackend.verifyNoOutstandingExpectation();
- $httpBackend.verifyNoOutstandingRequest();
- });
-
-
- it('should fetch authentication token', function() {
- $httpBackend.expectGET('/auth.py');
- var controller = scope.$new(MyController);
- $httpBackend.flush();
- });
-
-
- it('should send msg to server', function() {
- // now you don’t care about the authentication, but
- // the controller will still send the request and
- // $httpBackend will respond without you having to
- // specify the expectation and response for this request
- $httpBackend.expectPOST('/add-msg.py', 'message content').respond(201, '');
-
- var controller = scope.$new(MyController);
- $httpBackend.flush();
- controller.saveMessage('message content');
- expect(controller.status).toBe('Saving...');
- $httpBackend.flush();
- expect(controller.status).toBe('');
- });
-
-
- it('should send auth header', function() {
- $httpBackend.expectPOST('/add-msg.py', undefined, function(headers) {
- // check if the header was send, if it wasn't the expectation won't
- // match the request and the test will fail
- return headers['Authorization'] == 'xxx';
- }).respond(201, '');
-
- var controller = scope.$new(MyController);
- controller.saveMessage('whatever');
- $httpBackend.flush();
- });
-
- */
-angular.mock.$HttpBackendProvider = function() {
- this.$get = [createHttpBackendMock];
-};
-
-/**
- * General factory function for $httpBackend mock.
- * Returns instance for unit testing (when no arguments specified):
- * - passing through is disabled
- * - auto flushing is disabled
- *
- * Returns instance for e2e testing (when `$delegate` and `$browser` specified):
- * - passing through (delegating request to real backend) is enabled
- * - auto flushing is enabled
- *
- * @param {Object=} $delegate Real $httpBackend instance (allow passing through if specified)
- * @param {Object=} $browser Auto-flushing enabled if specified
- * @return {Object} Instance of $httpBackend mock
- */
-function createHttpBackendMock($delegate, $browser) {
- var definitions = [],
- expectations = [],
- responses = [],
- responsesPush = angular.bind(responses, responses.push);
-
- function createResponse(status, data, headers) {
- if (angular.isFunction(status)) return status;
-
- return function() {
- return angular.isNumber(status)
- ? [status, data, headers]
- : [200, status, data];
- };
- }
-
- // TODO(vojta): change params to: method, url, data, headers, callback
- function $httpBackend(method, url, data, callback, headers) {
- var xhr = new MockXhr(),
- expectation = expectations[0],
- wasExpected = false;
-
- function prettyPrint(data) {
- return (angular.isString(data) || angular.isFunction(data) || data instanceof RegExp)
- ? data
- : angular.toJson(data);
- }
-
- if (expectation && expectation.match(method, url)) {
- if (!expectation.matchData(data))
- throw Error('Expected ' + expectation + ' with different data\n' +
- 'EXPECTED: ' + prettyPrint(expectation.data) + '\nGOT: ' + data);
-
- if (!expectation.matchHeaders(headers))
- throw Error('Expected ' + expectation + ' with different headers\n' +
- 'EXPECTED: ' + prettyPrint(expectation.headers) + '\nGOT: ' +
- prettyPrint(headers));
-
- expectations.shift();
-
- if (expectation.response) {
- responses.push(function() {
- var response = expectation.response(method, url, data, headers);
- xhr.$$respHeaders = response[2];
- callback(response[0], response[1], xhr.getAllResponseHeaders());
- });
- return;
- }
- wasExpected = true;
- }
-
- var i = -1, definition;
- while ((definition = definitions[++i])) {
- if (definition.match(method, url, data, headers || {})) {
- if (definition.response) {
- // if $browser specified, we do auto flush all requests
- ($browser ? $browser.defer : responsesPush)(function() {
- var response = definition.response(method, url, data, headers);
- xhr.$$respHeaders = response[2];
- callback(response[0], response[1], xhr.getAllResponseHeaders());
- });
- } else if (definition.passThrough) {
- $delegate(method, url, data, callback, headers);
- } else throw Error('No response defined !');
- return;
- }
- }
- throw wasExpected ?
- Error('No response defined !') :
- Error('Unexpected request: ' + method + ' ' + url + '\n' +
- (expectation ? 'Expected ' + expectation : 'No more request expected'));
- }
-
- /**
- * @ngdoc method
- * @name ngMock.$httpBackend#when
- * @methodOf ngMock.$httpBackend
- * @description
- * Creates a new backend definition.
- *
- * @param {string} method HTTP method.
- * @param {string|RegExp} url HTTP url.
- * @param {(string|RegExp)=} data HTTP request body.
- * @param {(Object|function(Object))=} headers HTTP headers or function that receives http header
- * object and returns true if the headers match the current definition.
- * @returns {requestHandler} Returns an object with `respond` method that control how a matched
- * request is handled.
- *
- * - respond – `{function([status,] data[, headers])|function(function(method, url, data, headers)}`
- * – The respond method takes a set of static data to be returned or a function that can return
- * an array containing response status (number), response data (string) and response headers
- * (Object).
- */
- $httpBackend.when = function(method, url, data, headers) {
- var definition = new MockHttpExpectation(method, url, data, headers),
- chain = {
- respond: function(status, data, headers) {
- definition.response = createResponse(status, data, headers);
- }
- };
-
- if ($browser) {
- chain.passThrough = function() {
- definition.passThrough = true;
- };
- }
-
- definitions.push(definition);
- return chain;
- };
-
- /**
- * @ngdoc method
- * @name ngMock.$httpBackend#whenGET
- * @methodOf ngMock.$httpBackend
- * @description
- * Creates a new backend definition for GET requests. For more info see `when()`.
- *
- * @param {string|RegExp} url HTTP url.
- * @param {(Object|function(Object))=} headers HTTP headers.
- * @returns {requestHandler} Returns an object with `respond` method that control how a matched
- * request is handled.
- */
-
- /**
- * @ngdoc method
- * @name ngMock.$httpBackend#whenHEAD
- * @methodOf ngMock.$httpBackend
- * @description
- * Creates a new backend definition for HEAD requests. For more info see `when()`.
- *
- * @param {string|RegExp} url HTTP url.
- * @param {(Object|function(Object))=} headers HTTP headers.
- * @returns {requestHandler} Returns an object with `respond` method that control how a matched
- * request is handled.
- */
-
- /**
- * @ngdoc method
- * @name ngMock.$httpBackend#whenDELETE
- * @methodOf ngMock.$httpBackend
- * @description
- * Creates a new backend definition for DELETE requests. For more info see `when()`.
- *
- * @param {string|RegExp} url HTTP url.
- * @param {(Object|function(Object))=} headers HTTP headers.
- * @returns {requestHandler} Returns an object with `respond` method that control how a matched
- * request is handled.
- */
-
- /**
- * @ngdoc method
- * @name ngMock.$httpBackend#whenPOST
- * @methodOf ngMock.$httpBackend
- * @description
- * Creates a new backend definition for POST requests. For more info see `when()`.
- *
- * @param {string|RegExp} url HTTP url.
- * @param {(string|RegExp)=} data HTTP request body.
- * @param {(Object|function(Object))=} headers HTTP headers.
- * @returns {requestHandler} Returns an object with `respond` method that control how a matched
- * request is handled.
- */
-
- /**
- * @ngdoc method
- * @name ngMock.$httpBackend#whenPUT
- * @methodOf ngMock.$httpBackend
- * @description
- * Creates a new backend definition for PUT requests. For more info see `when()`.
- *
- * @param {string|RegExp} url HTTP url.
- * @param {(string|RegExp)=} data HTTP request body.
- * @param {(Object|function(Object))=} headers HTTP headers.
- * @returns {requestHandler} Returns an object with `respond` method that control how a matched
- * request is handled.
- */
-
- /**
- * @ngdoc method
- * @name ngMock.$httpBackend#whenJSONP
- * @methodOf ngMock.$httpBackend
- * @description
- * Creates a new backend definition for JSONP requests. For more info see `when()`.
- *
- * @param {string|RegExp} url HTTP url.
- * @returns {requestHandler} Returns an object with `respond` method that control how a matched
- * request is handled.
- */
- createShortMethods('when');
-
-
- /**
- * @ngdoc method
- * @name ngMock.$httpBackend#expect
- * @methodOf ngMock.$httpBackend
- * @description
- * Creates a new request expectation.
- *
- * @param {string} method HTTP method.
- * @param {string|RegExp} url HTTP url.
- * @param {(string|RegExp)=} data HTTP request body.
- * @param {(Object|function(Object))=} headers HTTP headers or function that receives http header
- * object and returns true if the headers match the current expectation.
- * @returns {requestHandler} Returns an object with `respond` method that control how a matched
- * request is handled.
- *
- * - respond – `{function([status,] data[, headers])|function(function(method, url, data, headers)}`
- * – The respond method takes a set of static data to be returned or a function that can return
- * an array containing response status (number), response data (string) and response headers
- * (Object).
- */
- $httpBackend.expect = function(method, url, data, headers) {
- var expectation = new MockHttpExpectation(method, url, data, headers);
- expectations.push(expectation);
- return {
- respond: function(status, data, headers) {
- expectation.response = createResponse(status, data, headers);
- }
- };
- };
-
-
- /**
- * @ngdoc method
- * @name ngMock.$httpBackend#expectGET
- * @methodOf ngMock.$httpBackend
- * @description
- * Creates a new request expectation for GET requests. For more info see `expect()`.
- *
- * @param {string|RegExp} url HTTP url.
- * @param {Object=} headers HTTP headers.
- * @returns {requestHandler} Returns an object with `respond` method that control how a matched
- * request is handled. See #expect for more info.
- */
-
- /**
- * @ngdoc method
- * @name ngMock.$httpBackend#expectHEAD
- * @methodOf ngMock.$httpBackend
- * @description
- * Creates a new request expectation for HEAD requests. For more info see `expect()`.
- *
- * @param {string|RegExp} url HTTP url.
- * @param {Object=} headers HTTP headers.
- * @returns {requestHandler} Returns an object with `respond` method that control how a matched
- * request is handled.
- */
-
- /**
- * @ngdoc method
- * @name ngMock.$httpBackend#expectDELETE
- * @methodOf ngMock.$httpBackend
- * @description
- * Creates a new request expectation for DELETE requests. For more info see `expect()`.
- *
- * @param {string|RegExp} url HTTP url.
- * @param {Object=} headers HTTP headers.
- * @returns {requestHandler} Returns an object with `respond` method that control how a matched
- * request is handled.
- */
-
- /**
- * @ngdoc method
- * @name ngMock.$httpBackend#expectPOST
- * @methodOf ngMock.$httpBackend
- * @description
- * Creates a new request expectation for POST requests. For more info see `expect()`.
- *
- * @param {string|RegExp} url HTTP url.
- * @param {(string|RegExp)=} data HTTP request body.
- * @param {Object=} headers HTTP headers.
- * @returns {requestHandler} Returns an object with `respond` method that control how a matched
- * request is handled.
- */
-
- /**
- * @ngdoc method
- * @name ngMock.$httpBackend#expectPUT
- * @methodOf ngMock.$httpBackend
- * @description
- * Creates a new request expectation for PUT requests. For more info see `expect()`.
- *
- * @param {string|RegExp} url HTTP url.
- * @param {(string|RegExp)=} data HTTP request body.
- * @param {Object=} headers HTTP headers.
- * @returns {requestHandler} Returns an object with `respond` method that control how a matched
- * request is handled.
- */
-
- /**
- * @ngdoc method
- * @name ngMock.$httpBackend#expectPATCH
- * @methodOf ngMock.$httpBackend
- * @description
- * Creates a new request expectation for PATCH requests. For more info see `expect()`.
- *
- * @param {string|RegExp} url HTTP url.
- * @param {(string|RegExp)=} data HTTP request body.
- * @param {Object=} headers HTTP headers.
- * @returns {requestHandler} Returns an object with `respond` method that control how a matched
- * request is handled.
- */
-
- /**
- * @ngdoc method
- * @name ngMock.$httpBackend#expectJSONP
- * @methodOf ngMock.$httpBackend
- * @description
- * Creates a new request expectation for JSONP requests. For more info see `expect()`.
- *
- * @param {string|RegExp} url HTTP url.
- * @returns {requestHandler} Returns an object with `respond` method that control how a matched
- * request is handled.
- */
- createShortMethods('expect');
-
-
- /**
- * @ngdoc method
- * @name ngMock.$httpBackend#flush
- * @methodOf ngMock.$httpBackend
- * @description
- * Flushes all pending requests using the trained responses.
- *
- * @param {number=} count Number of responses to flush (in the order they arrived). If undefined,
- * all pending requests will be flushed. If there are no pending requests when the flush method
- * is called an exception is thrown (as this typically a sign of programming error).
- */
- $httpBackend.flush = function(count) {
- if (!responses.length) throw Error('No pending request to flush !');
-
- if (angular.isDefined(count)) {
- while (count--) {
- if (!responses.length) throw Error('No more pending request to flush !');
- responses.shift()();
- }
- } else {
- while (responses.length) {
- responses.shift()();
- }
- }
- $httpBackend.verifyNoOutstandingExpectation();
- };
-
-
- /**
- * @ngdoc method
- * @name ngMock.$httpBackend#verifyNoOutstandingExpectation
- * @methodOf ngMock.$httpBackend
- * @description
- * Verifies that all of the requests defined via the `expect` api were made. If any of the
- * requests were not made, verifyNoOutstandingExpectation throws an exception.
- *
- * Typically, you would call this method following each test case that asserts requests using an
- * "afterEach" clause.
- *
- *
- */
- $httpBackend.verifyNoOutstandingExpectation = function() {
- if (expectations.length) {
- throw Error('Unsatisfied requests: ' + expectations.join(', '));
- }
- };
-
-
- /**
- * @ngdoc method
- * @name ngMock.$httpBackend#verifyNoOutstandingRequest
- * @methodOf ngMock.$httpBackend
- * @description
- * Verifies that there are no outstanding requests that need to be flushed.
- *
- * Typically, you would call this method following each test case that asserts requests using an
- * "afterEach" clause.
- *
- *
- */
- $httpBackend.verifyNoOutstandingRequest = function() {
- if (responses.length) {
- throw Error('Unflushed requests: ' + responses.length);
- }
- };
-
-
- /**
- * @ngdoc method
- * @name ngMock.$httpBackend#resetExpectations
- * @methodOf ngMock.$httpBackend
- * @description
- * Resets all request expectations, but preserves all backend definitions. Typically, you would
- * call resetExpectations during a multiple-phase test when you want to reuse the same instance of
- * $httpBackend mock.
- */
- $httpBackend.resetExpectations = function() {
- expectations.length = 0;
- responses.length = 0;
- };
-
- return $httpBackend;
-
-
- function createShortMethods(prefix) {
- angular.forEach(['GET', 'DELETE', 'JSONP'], function(method) {
- $httpBackend[prefix + method] = function(url, headers) {
- return $httpBackend[prefix](method, url, undefined, headers)
- }
- });
-
- angular.forEach(['PUT', 'POST', 'PATCH'], function(method) {
- $httpBackend[prefix + method] = function(url, data, headers) {
- return $httpBackend[prefix](method, url, data, headers)
- }
- });
- }
-}
-
-function MockHttpExpectation(method, url, data, headers) {
-
- this.data = data;
- this.headers = headers;
-
- this.match = function(m, u, d, h) {
- if (method != m) return false;
- if (!this.matchUrl(u)) return false;
- if (angular.isDefined(d) && !this.matchData(d)) return false;
- if (angular.isDefined(h) && !this.matchHeaders(h)) return false;
- return true;
- };
-
- this.matchUrl = function(u) {
- if (!url) return true;
- if (angular.isFunction(url.test)) return url.test(u);
- return url == u;
- };
-
- this.matchHeaders = function(h) {
- if (angular.isUndefined(headers)) return true;
- if (angular.isFunction(headers)) return headers(h);
- return angular.equals(headers, h);
- };
-
- this.matchData = function(d) {
- if (angular.isUndefined(data)) return true;
- if (data && angular.isFunction(data.test)) return data.test(d);
- if (data && !angular.isString(data)) return angular.toJson(data) == d;
- return data == d;
- };
-
- this.toString = function() {
- return method + ' ' + url;
- };
-}
-
-function MockXhr() {
-
- // hack for testing $http, $httpBackend
- MockXhr.$$lastInstance = this;
-
- this.open = function(method, url, async) {
- this.$$method = method;
- this.$$url = url;
- this.$$async = async;
- this.$$reqHeaders = {};
- this.$$respHeaders = {};
- };
-
- this.send = function(data) {
- this.$$data = data;
- };
-
- this.setRequestHeader = function(key, value) {
- this.$$reqHeaders[key] = value;
- };
-
- this.getResponseHeader = function(name) {
- // the lookup must be case insensitive, that's why we try two quick lookups and full scan at last
- var header = this.$$respHeaders[name];
- if (header) return header;
-
- name = angular.lowercase(name);
- header = this.$$respHeaders[name];
- if (header) return header;
-
- header = undefined;
- angular.forEach(this.$$respHeaders, function(headerVal, headerName) {
- if (!header && angular.lowercase(headerName) == name) header = headerVal;
- });
- return header;
- };
-
- this.getAllResponseHeaders = function() {
- var lines = [];
-
- angular.forEach(this.$$respHeaders, function(value, key) {
- lines.push(key + ': ' + value);
- });
- return lines.join('\n');
- };
-
- this.abort = angular.noop;
-}
-
-
-/**
- * @ngdoc function
- * @name ngMock.$timeout
- * @description
- *
- * This service is just a simple decorator for {@link ng.$timeout $timeout} service
- * that adds a "flush" method.
- */
-
-/**
- * @ngdoc method
- * @name ngMock.$timeout#flush
- * @methodOf ngMock.$timeout
- * @description
- *
- * Flushes the queue of pending tasks.
- */
-
-/**
- *
- */
-angular.mock.$RootElementProvider = function() {
- this.$get = function() {
- return angular.element('');
- }
-};
-
-/**
- * @ngdoc overview
- * @name ngMock
- * @description
- *
- * The `ngMock` is an angular module which is used with `ng` module and adds unit-test configuration as well as useful
- * mocks to the {@link AUTO.$injector $injector}.
- */
-angular.module('ngMock', ['ng']).provider({
- $browser: angular.mock.$BrowserProvider,
- $exceptionHandler: angular.mock.$ExceptionHandlerProvider,
- $log: angular.mock.$LogProvider,
- $httpBackend: angular.mock.$HttpBackendProvider,
- $rootElement: angular.mock.$RootElementProvider
-}).config(function($provide) {
- $provide.decorator('$timeout', function($delegate, $browser) {
- $delegate.flush = function() {
- $browser.defer.flush();
- };
- return $delegate;
- });
-});
-
-
-/**
- * @ngdoc overview
- * @name ngMockE2E
- * @description
- *
- * The `ngMockE2E` is an angular module which contains mocks suitable for end-to-end testing.
- * Currently there is only one mock present in this module -
- * the {@link ngMockE2E.$httpBackend e2e $httpBackend} mock.
- */
-angular.module('ngMockE2E', ['ng']).config(function($provide) {
- $provide.decorator('$httpBackend', angular.mock.e2e.$httpBackendDecorator);
-});
-
-/**
- * @ngdoc object
- * @name ngMockE2E.$httpBackend
- * @description
- * Fake HTTP backend implementation suitable for end-to-end testing or backend-less development of
- * applications that use the {@link ng.$http $http service}.
- *
- * *Note*: For fake http backend implementation suitable for unit testing please see
- * {@link ngMock.$httpBackend unit-testing $httpBackend mock}.
- *
- * This implementation can be used to respond with static or dynamic responses via the `when` api
- * and its shortcuts (`whenGET`, `whenPOST`, etc) and optionally pass through requests to the
- * real $httpBackend for specific requests (e.g. to interact with certain remote apis or to fetch
- * templates from a webserver).
- *
- * As opposed to unit-testing, in an end-to-end testing scenario or in scenario when an application
- * is being developed with the real backend api replaced with a mock, it is often desirable for
- * certain category of requests to bypass the mock and issue a real http request (e.g. to fetch
- * templates or static files from the webserver). To configure the backend with this behavior
- * use the `passThrough` request handler of `when` instead of `respond`.
- *
- * Additionally, we don't want to manually have to flush mocked out requests like we do during unit
- * testing. For this reason the e2e $httpBackend automatically flushes mocked out requests
- * automatically, closely simulating the behavior of the XMLHttpRequest object.
- *
- * To setup the application to run with this http backend, you have to create a module that depends
- * on the `ngMockE2E` and your application modules and defines the fake backend:
- *
- *
- * myAppDev = angular.module('myAppDev', ['myApp', 'ngMockE2E']);
- * myAppDev.run(function($httpBackend) {
- * phones = [{name: 'phone1'}, {name: 'phone2'}];
- *
- * // returns the current list of phones
- * $httpBackend.whenGET('/phones').respond(phones);
- *
- * // adds a new phone to the phones array
- * $httpBackend.whenPOST('/phones').respond(function(method, url, data) {
- * phones.push(angular.fromJSON(data));
- * });
- * $httpBackend.whenGET(/^\/templates\//).passThrough();
- * //...
- * });
- *
- *
- * Afterwards, bootstrap your app with this new module.
- */
-
-/**
- * @ngdoc method
- * @name ngMockE2E.$httpBackend#when
- * @methodOf ngMockE2E.$httpBackend
- * @description
- * Creates a new backend definition.
- *
- * @param {string} method HTTP method.
- * @param {string|RegExp} url HTTP url.
- * @param {(string|RegExp)=} data HTTP request body.
- * @param {(Object|function(Object))=} headers HTTP headers or function that receives http header
- * object and returns true if the headers match the current definition.
- * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that
- * control how a matched request is handled.
- *
- * - respond – `{function([status,] data[, headers])|function(function(method, url, data, headers)}`
- * – The respond method takes a set of static data to be returned or a function that can return
- * an array containing response status (number), response data (string) and response headers
- * (Object).
- * - passThrough – `{function()}` – Any request matching a backend definition with `passThrough`
- * handler, will be pass through to the real backend (an XHR request will be made to the
- * server.
- */
-
-/**
- * @ngdoc method
- * @name ngMockE2E.$httpBackend#whenGET
- * @methodOf ngMockE2E.$httpBackend
- * @description
- * Creates a new backend definition for GET requests. For more info see `when()`.
- *
- * @param {string|RegExp} url HTTP url.
- * @param {(Object|function(Object))=} headers HTTP headers.
- * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that
- * control how a matched request is handled.
- */
-
-/**
- * @ngdoc method
- * @name ngMockE2E.$httpBackend#whenHEAD
- * @methodOf ngMockE2E.$httpBackend
- * @description
- * Creates a new backend definition for HEAD requests. For more info see `when()`.
- *
- * @param {string|RegExp} url HTTP url.
- * @param {(Object|function(Object))=} headers HTTP headers.
- * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that
- * control how a matched request is handled.
- */
-
-/**
- * @ngdoc method
- * @name ngMockE2E.$httpBackend#whenDELETE
- * @methodOf ngMockE2E.$httpBackend
- * @description
- * Creates a new backend definition for DELETE requests. For more info see `when()`.
- *
- * @param {string|RegExp} url HTTP url.
- * @param {(Object|function(Object))=} headers HTTP headers.
- * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that
- * control how a matched request is handled.
- */
-
-/**
- * @ngdoc method
- * @name ngMockE2E.$httpBackend#whenPOST
- * @methodOf ngMockE2E.$httpBackend
- * @description
- * Creates a new backend definition for POST requests. For more info see `when()`.
- *
- * @param {string|RegExp} url HTTP url.
- * @param {(string|RegExp)=} data HTTP request body.
- * @param {(Object|function(Object))=} headers HTTP headers.
- * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that
- * control how a matched request is handled.
- */
-
-/**
- * @ngdoc method
- * @name ngMockE2E.$httpBackend#whenPUT
- * @methodOf ngMockE2E.$httpBackend
- * @description
- * Creates a new backend definition for PUT requests. For more info see `when()`.
- *
- * @param {string|RegExp} url HTTP url.
- * @param {(string|RegExp)=} data HTTP request body.
- * @param {(Object|function(Object))=} headers HTTP headers.
- * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that
- * control how a matched request is handled.
- */
-
-/**
- * @ngdoc method
- * @name ngMockE2E.$httpBackend#whenPATCH
- * @methodOf ngMockE2E.$httpBackend
- * @description
- * Creates a new backend definition for PATCH requests. For more info see `when()`.
- *
- * @param {string|RegExp} url HTTP url.
- * @param {(string|RegExp)=} data HTTP request body.
- * @param {(Object|function(Object))=} headers HTTP headers.
- * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that
- * control how a matched request is handled.
- */
-
-/**
- * @ngdoc method
- * @name ngMockE2E.$httpBackend#whenJSONP
- * @methodOf ngMockE2E.$httpBackend
- * @description
- * Creates a new backend definition for JSONP requests. For more info see `when()`.
- *
- * @param {string|RegExp} url HTTP url.
- * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that
- * control how a matched request is handled.
- */
-angular.mock.e2e = {};
-angular.mock.e2e.$httpBackendDecorator = ['$delegate', '$browser', createHttpBackendMock];
-
-
-angular.mock.clearDataCache = function() {
- var key,
- cache = angular.element.cache;
-
- for(key in cache) {
- if (cache.hasOwnProperty(key)) {
- var handle = cache[key].handle;
-
- handle && angular.element(handle.elem).unbind();
- delete cache[key];
- }
- }
-};
-
-
-window.jstestdriver && (function(window) {
- /**
- * Global method to output any number of objects into JSTD console. Useful for debugging.
- */
- window.dump = function() {
- var args = [];
- angular.forEach(arguments, function(arg) {
- args.push(angular.mock.dump(arg));
- });
- jstestdriver.console.log.apply(jstestdriver.console, args);
- if (window.console) {
- window.console.log.apply(window.console, args);
- }
- };
-})(window);
-
-
-window.jasmine && (function(window) {
-
- afterEach(function() {
- var spec = getCurrentSpec();
- var injector = spec.$injector;
-
- spec.$injector = null;
- spec.$modules = null;
-
- if (injector) {
- injector.get('$rootElement').unbind();
- injector.get('$browser').pollFns.length = 0;
- }
-
- angular.mock.clearDataCache();
-
- // clean up jquery's fragment cache
- angular.forEach(angular.element.fragments, function(val, key) {
- delete angular.element.fragments[key];
- });
-
- MockXhr.$$lastInstance = null;
-
- angular.forEach(angular.callbacks, function(val, key) {
- delete angular.callbacks[key];
- });
- angular.callbacks.counter = 0;
- });
-
- function getCurrentSpec() {
- return jasmine.getEnv().currentSpec;
- }
-
- function isSpecRunning() {
- var spec = getCurrentSpec();
- return spec && spec.queue.running;
- }
-
- /**
- * @ngdoc function
- * @name angular.mock.module
- * @description
- *
- * *NOTE*: This function is also published on window for easy access.
- * *NOTE*: Only available with {@link http://pivotal.github.com/jasmine/ jasmine}.
- *
- * This function registers a module configuration code. It collects the configuration information
- * which will be used when the injector is created by {@link angular.mock.inject inject}.
- *
- * See {@link angular.mock.inject inject} for usage example
- *
- * @param {...(string|Function)} fns any number of modules which are represented as string
- * aliases or as anonymous module initialization functions. The modules are used to
- * configure the injector. The 'ng' and 'ngMock' modules are automatically loaded.
- */
- window.module = angular.mock.module = function() {
- var moduleFns = Array.prototype.slice.call(arguments, 0);
- return isSpecRunning() ? workFn() : workFn;
- /////////////////////
- function workFn() {
- var spec = getCurrentSpec();
- if (spec.$injector) {
- throw Error('Injector already created, can not register a module!');
- } else {
- var modules = spec.$modules || (spec.$modules = []);
- angular.forEach(moduleFns, function(module) {
- modules.push(module);
- });
- }
- }
- };
-
- /**
- * @ngdoc function
- * @name angular.mock.inject
- * @description
- *
-<<<<<<< HEAD
- * *NOTE*: This is function is also published on window for easy access.
- * *NOTE*: Only available with {@link http://pivotal.github.com/jasmine/ jasmine}.
-=======
- * *NOTE*: This function is also published on window for easy access.
->>>>>>> 8dca056... docs(mocks): fix typos
- *
- * The inject function wraps a function into an injectable function. The inject() creates new
- * instance of {@link AUTO.$injector $injector} per test, which is then used for
- * resolving references.
- *
- * See also {@link angular.mock.module module}
- *
- * Example of what a typical jasmine tests looks like with the inject method.
- *
- *
- * angular.module('myApplicationModule', [])
- * .value('mode', 'app')
- * .value('version', 'v1.0.1');
- *
- *
- * describe('MyApp', function() {
- *
- * // You need to load modules that you want to test,
- * // it loads only the "ng" module by default.
- * beforeEach(module('myApplicationModule'));
- *
- *
- * // inject() is used to inject arguments of all given functions
- * it('should provide a version', inject(function(mode, version) {
- * expect(version).toEqual('v1.0.1');
- * expect(mode).toEqual('app');
- * }));
- *
- *
- * // The inject and module method can also be used inside of the it or beforeEach
- * it('should override a version and test the new version is injected', function() {
- * // module() takes functions or strings (module aliases)
- * module(function($provide) {
- * $provide.value('version', 'overridden'); // override version here
- * });
- *
- * inject(function(version) {
- * expect(version).toEqual('overridden');
- * });
- * ));
- * });
- *
- *
- *
- * @param {...Function} fns any number of functions which will be injected using the injector.
- */
- window.inject = angular.mock.inject = function() {
- var blockFns = Array.prototype.slice.call(arguments, 0);
- var errorForStack = new Error('Declaration Location');
- return isSpecRunning() ? workFn() : workFn;
- /////////////////////
- function workFn() {
- var spec = getCurrentSpec();
- var modules = spec.$modules || [];
- modules.unshift('ngMock');
- modules.unshift('ng');
- var injector = spec.$injector;
- if (!injector) {
- injector = spec.$injector = angular.injector(modules);
- }
- for(var i = 0, ii = blockFns.length; i < ii; i++) {
- try {
- injector.invoke(blockFns[i] || angular.noop, this);
- } catch (e) {
- if(e.stack && errorForStack) e.stack += '\n' + errorForStack.stack;
- throw e;
- } finally {
- errorForStack = null;
- }
- }
- }
- };
-})(window);
diff --git a/components/angular-mocks/bower.json b/components/angular-mocks/bower.json
deleted file mode 100644
index f961e15..0000000
--- a/components/angular-mocks/bower.json
+++ /dev/null
@@ -1,17 +0,0 @@
-{
- "name": "angular-mocks",
- "version": "1.0.6",
- "main": "./angular-mocks.js",
- "dependencies": {
- "angular": "1.0.6"
- },
- "gitHead": "aca28d63f8e64c794632eaa0f47d68b51c58b371",
- "readme": "bower-angular-mocks\n===================\n\nangular-mocks.js bower repo",
- "readmeFilename": "README.md",
- "_id": "angular-mocks@1.0.6",
- "description": "bower-angular-mocks ===================",
- "repository": {
- "type": "git",
- "url": "git://github.com/angular/bower-angular-mocks.git"
- }
-}
\ No newline at end of file
diff --git a/components/angular-scenario/README.md b/components/angular-scenario/README.md
deleted file mode 100644
index 1bcf564..0000000
--- a/components/angular-scenario/README.md
+++ /dev/null
@@ -1,4 +0,0 @@
-bower-angular-scenario
-======================
-
-bower repo for angular-scenario.js
\ No newline at end of file
diff --git a/components/angular-scenario/angular-scenario.js b/components/angular-scenario/angular-scenario.js
deleted file mode 100644
index c19b3de..0000000
--- a/components/angular-scenario/angular-scenario.js
+++ /dev/null
@@ -1,26223 +0,0 @@
-/*!
- * jQuery JavaScript Library v1.7.2
- * http://jquery.com/
- *
- * Copyright 2011, John Resig
- * Dual licensed under the MIT or GPL Version 2 licenses.
- * http://jquery.org/license
- *
- * Includes Sizzle.js
- * http://sizzlejs.com/
- * Copyright 2011, The Dojo Foundation
- * Released under the MIT, BSD, and GPL Licenses.
- *
- * Date: Wed Mar 21 12:46:34 2012 -0700
- */
-(function( window, undefined ) {
-'use strict';
-
-// Use the correct document accordingly with window argument (sandbox)
-var document = window.document,
- navigator = window.navigator,
- location = window.location;
-var jQuery = (function() {
-
-// Define a local copy of jQuery
-var jQuery = function( selector, context ) {
- // The jQuery object is actually just the init constructor 'enhanced'
- return new jQuery.fn.init( selector, context, rootjQuery );
- },
-
- // Map over jQuery in case of overwrite
- _jQuery = window.jQuery,
-
- // Map over the $ in case of overwrite
- _$ = window.$,
-
- // A central reference to the root jQuery(document)
- rootjQuery,
-
- // A simple way to check for HTML strings or ID strings
- // Prioritize #id over to avoid XSS via location.hash (#9521)
- quickExpr = /^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/,
-
- // Check if a string has a non-whitespace character in it
- rnotwhite = /\S/,
-
- // Used for trimming whitespace
- trimLeft = /^\s+/,
- trimRight = /\s+$/,
-
- // Match a standalone tag
- rsingleTag = /^<(\w+)\s*\/?>(?:<\/\1>)?$/,
-
- // JSON RegExp
- rvalidchars = /^[\],:{}\s]*$/,
- rvalidescape = /\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,
- rvalidtokens = /"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,
- rvalidbraces = /(?:^|:|,)(?:\s*\[)+/g,
-
- // Useragent RegExp
- rwebkit = /(webkit)[ \/]([\w.]+)/,
- ropera = /(opera)(?:.*version)?[ \/]([\w.]+)/,
- rmsie = /(msie) ([\w.]+)/,
- rmozilla = /(mozilla)(?:.*? rv:([\w.]+))?/,
-
- // Matches dashed string for camelizing
- rdashAlpha = /-([a-z]|[0-9])/ig,
- rmsPrefix = /^-ms-/,
-
- // Used by jQuery.camelCase as callback to replace()
- fcamelCase = function( all, letter ) {
- return ( letter + "" ).toUpperCase();
- },
-
- // Keep a UserAgent string for use with jQuery.browser
- userAgent = navigator.userAgent,
-
- // For matching the engine and version of the browser
- browserMatch,
-
- // The deferred used on DOM ready
- readyList,
-
- // The ready event handler
- DOMContentLoaded,
-
- // Save a reference to some core methods
- toString = Object.prototype.toString,
- hasOwn = Object.prototype.hasOwnProperty,
- push = Array.prototype.push,
- slice = Array.prototype.slice,
- trim = String.prototype.trim,
- indexOf = Array.prototype.indexOf,
-
- // [[Class]] -> type pairs
- class2type = {};
-
-jQuery.fn = jQuery.prototype = {
- constructor: jQuery,
- init: function( selector, context, rootjQuery ) {
- var match, elem, ret, doc;
-
- // Handle $(""), $(null), or $(undefined)
- if ( !selector ) {
- return this;
- }
-
- // Handle $(DOMElement)
- if ( selector.nodeType ) {
- this.context = this[0] = selector;
- this.length = 1;
- return this;
- }
-
- // The body element only exists once, optimize finding it
- if ( selector === "body" && !context && document.body ) {
- this.context = document;
- this[0] = document.body;
- this.selector = selector;
- this.length = 1;
- return this;
- }
-
- // Handle HTML strings
- if ( typeof selector === "string" ) {
- // Are we dealing with HTML string or an ID?
- if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) {
- // Assume that strings that start and end with <> are HTML and skip the regex check
- match = [ null, selector, null ];
-
- } else {
- match = quickExpr.exec( selector );
- }
-
- // Verify a match, and that no context was specified for #id
- if ( match && (match[1] || !context) ) {
-
- // HANDLE: $(html) -> $(array)
- if ( match[1] ) {
- context = context instanceof jQuery ? context[0] : context;
- doc = ( context ? context.ownerDocument || context : document );
-
- // If a single string is passed in and it's a single tag
- // just do a createElement and skip the rest
- ret = rsingleTag.exec( selector );
-
- if ( ret ) {
- if ( jQuery.isPlainObject( context ) ) {
- selector = [ document.createElement( ret[1] ) ];
- jQuery.fn.attr.call( selector, context, true );
-
- } else {
- selector = [ doc.createElement( ret[1] ) ];
- }
-
- } else {
- ret = jQuery.buildFragment( [ match[1] ], [ doc ] );
- selector = ( ret.cacheable ? jQuery.clone(ret.fragment) : ret.fragment ).childNodes;
- }
-
- return jQuery.merge( this, selector );
-
- // HANDLE: $("#id")
- } else {
- elem = document.getElementById( match[2] );
-
- // Check parentNode to catch when Blackberry 4.6 returns
- // nodes that are no longer in the document #6963
- if ( elem && elem.parentNode ) {
- // Handle the case where IE and Opera return items
- // by name instead of ID
- if ( elem.id !== match[2] ) {
- return rootjQuery.find( selector );
- }
-
- // Otherwise, we inject the element directly into the jQuery object
- this.length = 1;
- this[0] = elem;
- }
-
- this.context = document;
- this.selector = selector;
- return this;
- }
-
- // HANDLE: $(expr, $(...))
- } else if ( !context || context.jquery ) {
- return ( context || rootjQuery ).find( selector );
-
- // HANDLE: $(expr, context)
- // (which is just equivalent to: $(context).find(expr)
- } else {
- return this.constructor( context ).find( selector );
- }
-
- // HANDLE: $(function)
- // Shortcut for document ready
- } else if ( jQuery.isFunction( selector ) ) {
- return rootjQuery.ready( selector );
- }
-
- if ( selector.selector !== undefined ) {
- this.selector = selector.selector;
- this.context = selector.context;
- }
-
- return jQuery.makeArray( selector, this );
- },
-
- // Start with an empty selector
- selector: "",
-
- // The current version of jQuery being used
- jquery: "1.7.2",
-
- // The default length of a jQuery object is 0
- length: 0,
-
- // The number of elements contained in the matched element set
- size: function() {
- return this.length;
- },
-
- toArray: function() {
- return slice.call( this, 0 );
- },
-
- // Get the Nth element in the matched element set OR
- // Get the whole matched element set as a clean array
- get: function( num ) {
- return num == null ?
-
- // Return a 'clean' array
- this.toArray() :
-
- // Return just the object
- ( num < 0 ? this[ this.length + num ] : this[ num ] );
- },
-
- // Take an array of elements and push it onto the stack
- // (returning the new matched element set)
- pushStack: function( elems, name, selector ) {
- // Build a new jQuery matched element set
- var ret = this.constructor();
-
- if ( jQuery.isArray( elems ) ) {
- push.apply( ret, elems );
-
- } else {
- jQuery.merge( ret, elems );
- }
-
- // Add the old object onto the stack (as a reference)
- ret.prevObject = this;
-
- ret.context = this.context;
-
- if ( name === "find" ) {
- ret.selector = this.selector + ( this.selector ? " " : "" ) + selector;
- } else if ( name ) {
- ret.selector = this.selector + "." + name + "(" + selector + ")";
- }
-
- // Return the newly-formed element set
- return ret;
- },
-
- // Execute a callback for every element in the matched set.
- // (You can seed the arguments with an array of args, but this is
- // only used internally.)
- each: function( callback, args ) {
- return jQuery.each( this, callback, args );
- },
-
- ready: function( fn ) {
- // Attach the listeners
- jQuery.bindReady();
-
- // Add the callback
- readyList.add( fn );
-
- return this;
- },
-
- eq: function( i ) {
- i = +i;
- return i === -1 ?
- this.slice( i ) :
- this.slice( i, i + 1 );
- },
-
- first: function() {
- return this.eq( 0 );
- },
-
- last: function() {
- return this.eq( -1 );
- },
-
- slice: function() {
- return this.pushStack( slice.apply( this, arguments ),
- "slice", slice.call(arguments).join(",") );
- },
-
- map: function( callback ) {
- return this.pushStack( jQuery.map(this, function( elem, i ) {
- return callback.call( elem, i, elem );
- }));
- },
-
- end: function() {
- return this.prevObject || this.constructor(null);
- },
-
- // For internal use only.
- // Behaves like an Array's method, not like a jQuery method.
- push: push,
- sort: [].sort,
- splice: [].splice
-};
-
-// Give the init function the jQuery prototype for later instantiation
-jQuery.fn.init.prototype = jQuery.fn;
-
-jQuery.extend = jQuery.fn.extend = function() {
- var options, name, src, copy, copyIsArray, clone,
- target = arguments[0] || {},
- i = 1,
- length = arguments.length,
- deep = false;
-
- // Handle a deep copy situation
- if ( typeof target === "boolean" ) {
- deep = target;
- target = arguments[1] || {};
- // skip the boolean and the target
- i = 2;
- }
-
- // Handle case when target is a string or something (possible in deep copy)
- if ( typeof target !== "object" && !jQuery.isFunction(target) ) {
- target = {};
- }
-
- // extend jQuery itself if only one argument is passed
- if ( length === i ) {
- target = this;
- --i;
- }
-
- for ( ; i < length; i++ ) {
- // Only deal with non-null/undefined values
- if ( (options = arguments[ i ]) != null ) {
- // Extend the base object
- for ( name in options ) {
- src = target[ name ];
- copy = options[ name ];
-
- // Prevent never-ending loop
- if ( target === copy ) {
- continue;
- }
-
- // Recurse if we're merging plain objects or arrays
- if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) {
- if ( copyIsArray ) {
- copyIsArray = false;
- clone = src && jQuery.isArray(src) ? src : [];
-
- } else {
- clone = src && jQuery.isPlainObject(src) ? src : {};
- }
-
- // Never move original objects, clone them
- target[ name ] = jQuery.extend( deep, clone, copy );
-
- // Don't bring in undefined values
- } else if ( copy !== undefined ) {
- target[ name ] = copy;
- }
- }
- }
- }
-
- // Return the modified object
- return target;
-};
-
-jQuery.extend({
- noConflict: function( deep ) {
- if ( window.$ === jQuery ) {
- window.$ = _$;
- }
-
- if ( deep && window.jQuery === jQuery ) {
- window.jQuery = _jQuery;
- }
-
- return jQuery;
- },
-
- // Is the DOM ready to be used? Set to true once it occurs.
- isReady: false,
-
- // A counter to track how many items to wait for before
- // the ready event fires. See #6781
- readyWait: 1,
-
- // Hold (or release) the ready event
- holdReady: function( hold ) {
- if ( hold ) {
- jQuery.readyWait++;
- } else {
- jQuery.ready( true );
- }
- },
-
- // Handle when the DOM is ready
- ready: function( wait ) {
- // Either a released hold or an DOMready/load event and not yet ready
- if ( (wait === true && !--jQuery.readyWait) || (wait !== true && !jQuery.isReady) ) {
- // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).
- if ( !document.body ) {
- return setTimeout( jQuery.ready, 1 );
- }
-
- // Remember that the DOM is ready
- jQuery.isReady = true;
-
- // If a normal DOM Ready event fired, decrement, and wait if need be
- if ( wait !== true && --jQuery.readyWait > 0 ) {
- return;
- }
-
- // If there are functions bound, to execute
- readyList.fireWith( document, [ jQuery ] );
-
- // Trigger any bound ready events
- if ( jQuery.fn.trigger ) {
- jQuery( document ).trigger( "ready" ).off( "ready" );
- }
- }
- },
-
- bindReady: function() {
- if ( readyList ) {
- return;
- }
-
- readyList = jQuery.Callbacks( "once memory" );
-
- // Catch cases where $(document).ready() is called after the
- // browser event has already occurred.
- if ( document.readyState === "complete" ) {
- // Handle it asynchronously to allow scripts the opportunity to delay ready
- return setTimeout( jQuery.ready, 1 );
- }
-
- // Mozilla, Opera and webkit nightlies currently support this event
- if ( document.addEventListener ) {
- // Use the handy event callback
- document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false );
-
- // A fallback to window.onload, that will always work
- window.addEventListener( "load", jQuery.ready, false );
-
- // If IE event model is used
- } else if ( document.attachEvent ) {
- // ensure firing before onload,
- // maybe late but safe also for iframes
- document.attachEvent( "onreadystatechange", DOMContentLoaded );
-
- // A fallback to window.onload, that will always work
- window.attachEvent( "onload", jQuery.ready );
-
- // If IE and not a frame
- // continually check to see if the document is ready
- var toplevel = false;
-
- try {
- toplevel = window.frameElement == null;
- } catch(e) {}
-
- if ( document.documentElement.doScroll && toplevel ) {
- doScrollCheck();
- }
- }
- },
-
- // See test/unit/core.js for details concerning isFunction.
- // Since version 1.3, DOM methods and functions like alert
- // aren't supported. They return false on IE (#2968).
- isFunction: function( obj ) {
- return jQuery.type(obj) === "function";
- },
-
- isArray: Array.isArray || function( obj ) {
- return jQuery.type(obj) === "array";
- },
-
- isWindow: function( obj ) {
- return obj != null && obj == obj.window;
- },
-
- isNumeric: function( obj ) {
- return !isNaN( parseFloat(obj) ) && isFinite( obj );
- },
-
- type: function( obj ) {
- return obj == null ?
- String( obj ) :
- class2type[ toString.call(obj) ] || "object";
- },
-
- isPlainObject: function( obj ) {
- // Must be an Object.
- // Because of IE, we also have to check the presence of the constructor property.
- // Make sure that DOM nodes and window objects don't pass through, as well
- if ( !obj || jQuery.type(obj) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) {
- return false;
- }
-
- try {
- // Not own constructor property must be Object
- if ( obj.constructor &&
- !hasOwn.call(obj, "constructor") &&
- !hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) {
- return false;
- }
- } catch ( e ) {
- // IE8,9 Will throw exceptions on certain host objects #9897
- return false;
- }
-
- // Own properties are enumerated firstly, so to speed up,
- // if last one is own, then all properties are own.
-
- var key;
- for ( key in obj ) {}
-
- return key === undefined || hasOwn.call( obj, key );
- },
-
- isEmptyObject: function( obj ) {
- for ( var name in obj ) {
- return false;
- }
- return true;
- },
-
- error: function( msg ) {
- throw new Error( msg );
- },
-
- parseJSON: function( data ) {
- if ( typeof data !== "string" || !data ) {
- return null;
- }
-
- // Make sure leading/trailing whitespace is removed (IE can't handle it)
- data = jQuery.trim( data );
-
- // Attempt to parse using the native JSON parser first
- if ( window.JSON && window.JSON.parse ) {
- return window.JSON.parse( data );
- }
-
- // Make sure the incoming data is actual JSON
- // Logic borrowed from http://json.org/json2.js
- if ( rvalidchars.test( data.replace( rvalidescape, "@" )
- .replace( rvalidtokens, "]" )
- .replace( rvalidbraces, "")) ) {
-
- return ( new Function( "return " + data ) )();
-
- }
- jQuery.error( "Invalid JSON: " + data );
- },
-
- // Cross-browser xml parsing
- parseXML: function( data ) {
- if ( typeof data !== "string" || !data ) {
- return null;
- }
- var xml, tmp;
- try {
- if ( window.DOMParser ) { // Standard
- tmp = new DOMParser();
- xml = tmp.parseFromString( data , "text/xml" );
- } else { // IE
- xml = new ActiveXObject( "Microsoft.XMLDOM" );
- xml.async = "false";
- xml.loadXML( data );
- }
- } catch( e ) {
- xml = undefined;
- }
- if ( !xml || !xml.documentElement || xml.getElementsByTagName( "parsererror" ).length ) {
- jQuery.error( "Invalid XML: " + data );
- }
- return xml;
- },
-
- noop: function() {},
-
- // Evaluates a script in a global context
- // Workarounds based on findings by Jim Driscoll
- // http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context
- globalEval: function( data ) {
- if ( data && rnotwhite.test( data ) ) {
- // We use execScript on Internet Explorer
- // We use an anonymous function so that context is window
- // rather than jQuery in Firefox
- ( window.execScript || function( data ) {
- window[ "eval" ].call( window, data );
- } )( data );
- }
- },
-
- // Convert dashed to camelCase; used by the css and data modules
- // Microsoft forgot to hump their vendor prefix (#9572)
- camelCase: function( string ) {
- return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase );
- },
-
- nodeName: function( elem, name ) {
- return elem.nodeName && elem.nodeName.toUpperCase() === name.toUpperCase();
- },
-
- // args is for internal usage only
- each: function( object, callback, args ) {
- var name, i = 0,
- length = object.length,
- isObj = length === undefined || jQuery.isFunction( object );
-
- if ( args ) {
- if ( isObj ) {
- for ( name in object ) {
- if ( callback.apply( object[ name ], args ) === false ) {
- break;
- }
- }
- } else {
- for ( ; i < length; ) {
- if ( callback.apply( object[ i++ ], args ) === false ) {
- break;
- }
- }
- }
-
- // A special, fast, case for the most common use of each
- } else {
- if ( isObj ) {
- for ( name in object ) {
- if ( callback.call( object[ name ], name, object[ name ] ) === false ) {
- break;
- }
- }
- } else {
- for ( ; i < length; ) {
- if ( callback.call( object[ i ], i, object[ i++ ] ) === false ) {
- break;
- }
- }
- }
- }
-
- return object;
- },
-
- // Use native String.trim function wherever possible
- trim: trim ?
- function( text ) {
- return text == null ?
- "" :
- trim.call( text );
- } :
-
- // Otherwise use our own trimming functionality
- function( text ) {
- return text == null ?
- "" :
- text.toString().replace( trimLeft, "" ).replace( trimRight, "" );
- },
-
- // results is for internal usage only
- makeArray: function( array, results ) {
- var ret = results || [];
-
- if ( array != null ) {
- // The window, strings (and functions) also have 'length'
- // Tweaked logic slightly to handle Blackberry 4.7 RegExp issues #6930
- var type = jQuery.type( array );
-
- if ( array.length == null || type === "string" || type === "function" || type === "regexp" || jQuery.isWindow( array ) ) {
- push.call( ret, array );
- } else {
- jQuery.merge( ret, array );
- }
- }
-
- return ret;
- },
-
- inArray: function( elem, array, i ) {
- var len;
-
- if ( array ) {
- if ( indexOf ) {
- return indexOf.call( array, elem, i );
- }
-
- len = array.length;
- i = i ? i < 0 ? Math.max( 0, len + i ) : i : 0;
-
- for ( ; i < len; i++ ) {
- // Skip accessing in sparse arrays
- if ( i in array && array[ i ] === elem ) {
- return i;
- }
- }
- }
-
- return -1;
- },
-
- merge: function( first, second ) {
- var i = first.length,
- j = 0;
-
- if ( typeof second.length === "number" ) {
- for ( var l = second.length; j < l; j++ ) {
- first[ i++ ] = second[ j ];
- }
-
- } else {
- while ( second[j] !== undefined ) {
- first[ i++ ] = second[ j++ ];
- }
- }
-
- first.length = i;
-
- return first;
- },
-
- grep: function( elems, callback, inv ) {
- var ret = [], retVal;
- inv = !!inv;
-
- // Go through the array, only saving the items
- // that pass the validator function
- for ( var i = 0, length = elems.length; i < length; i++ ) {
- retVal = !!callback( elems[ i ], i );
- if ( inv !== retVal ) {
- ret.push( elems[ i ] );
- }
- }
-
- return ret;
- },
-
- // arg is for internal usage only
- map: function( elems, callback, arg ) {
- var value, key, ret = [],
- i = 0,
- length = elems.length,
- // jquery objects are treated as arrays
- isArray = elems instanceof jQuery || length !== undefined && typeof length === "number" && ( ( length > 0 && elems[ 0 ] && elems[ length -1 ] ) || length === 0 || jQuery.isArray( elems ) ) ;
-
- // Go through the array, translating each of the items to their
- if ( isArray ) {
- for ( ; i < length; i++ ) {
- value = callback( elems[ i ], i, arg );
-
- if ( value != null ) {
- ret[ ret.length ] = value;
- }
- }
-
- // Go through every key on the object,
- } else {
- for ( key in elems ) {
- value = callback( elems[ key ], key, arg );
-
- if ( value != null ) {
- ret[ ret.length ] = value;
- }
- }
- }
-
- // Flatten any nested arrays
- return ret.concat.apply( [], ret );
- },
-
- // A global GUID counter for objects
- guid: 1,
-
- // Bind a function to a context, optionally partially applying any
- // arguments.
- proxy: function( fn, context ) {
- if ( typeof context === "string" ) {
- var tmp = fn[ context ];
- context = fn;
- fn = tmp;
- }
-
- // Quick check to determine if target is callable, in the spec
- // this throws a TypeError, but we will just return undefined.
- if ( !jQuery.isFunction( fn ) ) {
- return undefined;
- }
-
- // Simulated bind
- var args = slice.call( arguments, 2 ),
- proxy = function() {
- return fn.apply( context, args.concat( slice.call( arguments ) ) );
- };
-
- // Set the guid of unique handler to the same of original handler, so it can be removed
- proxy.guid = fn.guid = fn.guid || proxy.guid || jQuery.guid++;
-
- return proxy;
- },
-
- // Mutifunctional method to get and set values to a collection
- // The value/s can optionally be executed if it's a function
- access: function( elems, fn, key, value, chainable, emptyGet, pass ) {
- var exec,
- bulk = key == null,
- i = 0,
- length = elems.length;
-
- // Sets many values
- if ( key && typeof key === "object" ) {
- for ( i in key ) {
- jQuery.access( elems, fn, i, key[i], 1, emptyGet, value );
- }
- chainable = 1;
-
- // Sets one value
- } else if ( value !== undefined ) {
- // Optionally, function values get executed if exec is true
- exec = pass === undefined && jQuery.isFunction( value );
-
- if ( bulk ) {
- // Bulk operations only iterate when executing function values
- if ( exec ) {
- exec = fn;
- fn = function( elem, key, value ) {
- return exec.call( jQuery( elem ), value );
- };
-
- // Otherwise they run against the entire set
- } else {
- fn.call( elems, value );
- fn = null;
- }
- }
-
- if ( fn ) {
- for (; i < length; i++ ) {
- fn( elems[i], key, exec ? value.call( elems[i], i, fn( elems[i], key ) ) : value, pass );
- }
- }
-
- chainable = 1;
- }
-
- return chainable ?
- elems :
-
- // Gets
- bulk ?
- fn.call( elems ) :
- length ? fn( elems[0], key ) : emptyGet;
- },
-
- now: function() {
- return ( new Date() ).getTime();
- },
-
- // Use of jQuery.browser is frowned upon.
- // More details: http://docs.jquery.com/Utilities/jQuery.browser
- uaMatch: function( ua ) {
- ua = ua.toLowerCase();
-
- var match = rwebkit.exec( ua ) ||
- ropera.exec( ua ) ||
- rmsie.exec( ua ) ||
- ua.indexOf("compatible") < 0 && rmozilla.exec( ua ) ||
- [];
-
- return { browser: match[1] || "", version: match[2] || "0" };
- },
-
- sub: function() {
- function jQuerySub( selector, context ) {
- return new jQuerySub.fn.init( selector, context );
- }
- jQuery.extend( true, jQuerySub, this );
- jQuerySub.superclass = this;
- jQuerySub.fn = jQuerySub.prototype = this();
- jQuerySub.fn.constructor = jQuerySub;
- jQuerySub.sub = this.sub;
- jQuerySub.fn.init = function init( selector, context ) {
- if ( context && context instanceof jQuery && !(context instanceof jQuerySub) ) {
- context = jQuerySub( context );
- }
-
- return jQuery.fn.init.call( this, selector, context, rootjQuerySub );
- };
- jQuerySub.fn.init.prototype = jQuerySub.fn;
- var rootjQuerySub = jQuerySub(document);
- return jQuerySub;
- },
-
- browser: {}
-});
-
-// Populate the class2type map
-jQuery.each("Boolean Number String Function Array Date RegExp Object".split(" "), function(i, name) {
- class2type[ "[object " + name + "]" ] = name.toLowerCase();
-});
-
-browserMatch = jQuery.uaMatch( userAgent );
-if ( browserMatch.browser ) {
- jQuery.browser[ browserMatch.browser ] = true;
- jQuery.browser.version = browserMatch.version;
-}
-
-// Deprecated, use jQuery.browser.webkit instead
-if ( jQuery.browser.webkit ) {
- jQuery.browser.safari = true;
-}
-
-// IE doesn't match non-breaking spaces with \s
-if ( rnotwhite.test( "\xA0" ) ) {
- trimLeft = /^[\s\xA0]+/;
- trimRight = /[\s\xA0]+$/;
-}
-
-// All jQuery objects should point back to these
-rootjQuery = jQuery(document);
-
-// Cleanup functions for the document ready method
-if ( document.addEventListener ) {
- DOMContentLoaded = function() {
- document.removeEventListener( "DOMContentLoaded", DOMContentLoaded, false );
- jQuery.ready();
- };
-
-} else if ( document.attachEvent ) {
- DOMContentLoaded = function() {
- // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).
- if ( document.readyState === "complete" ) {
- document.detachEvent( "onreadystatechange", DOMContentLoaded );
- jQuery.ready();
- }
- };
-}
-
-// The DOM ready check for Internet Explorer
-function doScrollCheck() {
- if ( jQuery.isReady ) {
- return;
- }
-
- try {
- // If IE is used, use the trick by Diego Perini
- // http://javascript.nwbox.com/IEContentLoaded/
- document.documentElement.doScroll("left");
- } catch(e) {
- setTimeout( doScrollCheck, 1 );
- return;
- }
-
- // and execute any waiting functions
- jQuery.ready();
-}
-
-return jQuery;
-
-})();
-
-
-// String to Object flags format cache
-var flagsCache = {};
-
-// Convert String-formatted flags into Object-formatted ones and store in cache
-function createFlags( flags ) {
- var object = flagsCache[ flags ] = {},
- i, length;
- flags = flags.split( /\s+/ );
- for ( i = 0, length = flags.length; i < length; i++ ) {
- object[ flags[i] ] = true;
- }
- return object;
-}
-
-/*
- * Create a callback list using the following parameters:
- *
- * flags: an optional list of space-separated flags that will change how
- * the callback list behaves
- *
- * By default a callback list will act like an event callback list and can be
- * "fired" multiple times.
- *
- * Possible flags:
- *
- * once: will ensure the callback list can only be fired once (like a Deferred)
- *
- * memory: will keep track of previous values and will call any callback added
- * after the list has been fired right away with the latest "memorized"
- * values (like a Deferred)
- *
- * unique: will ensure a callback can only be added once (no duplicate in the list)
- *
- * stopOnFalse: interrupt callings when a callback returns false
- *
- */
-jQuery.Callbacks = function( flags ) {
-
- // Convert flags from String-formatted to Object-formatted
- // (we check in cache first)
- flags = flags ? ( flagsCache[ flags ] || createFlags( flags ) ) : {};
-
- var // Actual callback list
- list = [],
- // Stack of fire calls for repeatable lists
- stack = [],
- // Last fire value (for non-forgettable lists)
- memory,
- // Flag to know if list was already fired
- fired,
- // Flag to know if list is currently firing
- firing,
- // First callback to fire (used internally by add and fireWith)
- firingStart,
- // End of the loop when firing
- firingLength,
- // Index of currently firing callback (modified by remove if needed)
- firingIndex,
- // Add one or several callbacks to the list
- add = function( args ) {
- var i,
- length,
- elem,
- type,
- actual;
- for ( i = 0, length = args.length; i < length; i++ ) {
- elem = args[ i ];
- type = jQuery.type( elem );
- if ( type === "array" ) {
- // Inspect recursively
- add( elem );
- } else if ( type === "function" ) {
- // Add if not in unique mode and callback is not in
- if ( !flags.unique || !self.has( elem ) ) {
- list.push( elem );
- }
- }
- }
- },
- // Fire callbacks
- fire = function( context, args ) {
- args = args || [];
- memory = !flags.memory || [ context, args ];
- fired = true;
- firing = true;
- firingIndex = firingStart || 0;
- firingStart = 0;
- firingLength = list.length;
- for ( ; list && firingIndex < firingLength; firingIndex++ ) {
- if ( list[ firingIndex ].apply( context, args ) === false && flags.stopOnFalse ) {
- memory = true; // Mark as halted
- break;
- }
- }
- firing = false;
- if ( list ) {
- if ( !flags.once ) {
- if ( stack && stack.length ) {
- memory = stack.shift();
- self.fireWith( memory[ 0 ], memory[ 1 ] );
- }
- } else if ( memory === true ) {
- self.disable();
- } else {
- list = [];
- }
- }
- },
- // Actual Callbacks object
- self = {
- // Add a callback or a collection of callbacks to the list
- add: function() {
- if ( list ) {
- var length = list.length;
- add( arguments );
- // Do we need to add the callbacks to the
- // current firing batch?
- if ( firing ) {
- firingLength = list.length;
- // With memory, if we're not firing then
- // we should call right away, unless previous
- // firing was halted (stopOnFalse)
- } else if ( memory && memory !== true ) {
- firingStart = length;
- fire( memory[ 0 ], memory[ 1 ] );
- }
- }
- return this;
- },
- // Remove a callback from the list
- remove: function() {
- if ( list ) {
- var args = arguments,
- argIndex = 0,
- argLength = args.length;
- for ( ; argIndex < argLength ; argIndex++ ) {
- for ( var i = 0; i < list.length; i++ ) {
- if ( args[ argIndex ] === list[ i ] ) {
- // Handle firingIndex and firingLength
- if ( firing ) {
- if ( i <= firingLength ) {
- firingLength--;
- if ( i <= firingIndex ) {
- firingIndex--;
- }
- }
- }
- // Remove the element
- list.splice( i--, 1 );
- // If we have some unicity property then
- // we only need to do this once
- if ( flags.unique ) {
- break;
- }
- }
- }
- }
- }
- return this;
- },
- // Control if a given callback is in the list
- has: function( fn ) {
- if ( list ) {
- var i = 0,
- length = list.length;
- for ( ; i < length; i++ ) {
- if ( fn === list[ i ] ) {
- return true;
- }
- }
- }
- return false;
- },
- // Remove all callbacks from the list
- empty: function() {
- list = [];
- return this;
- },
- // Have the list do nothing anymore
- disable: function() {
- list = stack = memory = undefined;
- return this;
- },
- // Is it disabled?
- disabled: function() {
- return !list;
- },
- // Lock the list in its current state
- lock: function() {
- stack = undefined;
- if ( !memory || memory === true ) {
- self.disable();
- }
- return this;
- },
- // Is it locked?
- locked: function() {
- return !stack;
- },
- // Call all callbacks with the given context and arguments
- fireWith: function( context, args ) {
- if ( stack ) {
- if ( firing ) {
- if ( !flags.once ) {
- stack.push( [ context, args ] );
- }
- } else if ( !( flags.once && memory ) ) {
- fire( context, args );
- }
- }
- return this;
- },
- // Call all the callbacks with the given arguments
- fire: function() {
- self.fireWith( this, arguments );
- return this;
- },
- // To know if the callbacks have already been called at least once
- fired: function() {
- return !!fired;
- }
- };
-
- return self;
-};
-
-
-
-
-var // Static reference to slice
- sliceDeferred = [].slice;
-
-jQuery.extend({
-
- Deferred: function( func ) {
- var doneList = jQuery.Callbacks( "once memory" ),
- failList = jQuery.Callbacks( "once memory" ),
- progressList = jQuery.Callbacks( "memory" ),
- state = "pending",
- lists = {
- resolve: doneList,
- reject: failList,
- notify: progressList
- },
- promise = {
- done: doneList.add,
- fail: failList.add,
- progress: progressList.add,
-
- state: function() {
- return state;
- },
-
- // Deprecated
- isResolved: doneList.fired,
- isRejected: failList.fired,
-
- then: function( doneCallbacks, failCallbacks, progressCallbacks ) {
- deferred.done( doneCallbacks ).fail( failCallbacks ).progress( progressCallbacks );
- return this;
- },
- always: function() {
- deferred.done.apply( deferred, arguments ).fail.apply( deferred, arguments );
- return this;
- },
- pipe: function( fnDone, fnFail, fnProgress ) {
- return jQuery.Deferred(function( newDefer ) {
- jQuery.each( {
- done: [ fnDone, "resolve" ],
- fail: [ fnFail, "reject" ],
- progress: [ fnProgress, "notify" ]
- }, function( handler, data ) {
- var fn = data[ 0 ],
- action = data[ 1 ],
- returned;
- if ( jQuery.isFunction( fn ) ) {
- deferred[ handler ](function() {
- returned = fn.apply( this, arguments );
- if ( returned && jQuery.isFunction( returned.promise ) ) {
- returned.promise().then( newDefer.resolve, newDefer.reject, newDefer.notify );
- } else {
- newDefer[ action + "With" ]( this === deferred ? newDefer : this, [ returned ] );
- }
- });
- } else {
- deferred[ handler ]( newDefer[ action ] );
- }
- });
- }).promise();
- },
- // Get a promise for this deferred
- // If obj is provided, the promise aspect is added to the object
- promise: function( obj ) {
- if ( obj == null ) {
- obj = promise;
- } else {
- for ( var key in promise ) {
- obj[ key ] = promise[ key ];
- }
- }
- return obj;
- }
- },
- deferred = promise.promise({}),
- key;
-
- for ( key in lists ) {
- deferred[ key ] = lists[ key ].fire;
- deferred[ key + "With" ] = lists[ key ].fireWith;
- }
-
- // Handle state
- deferred.done( function() {
- state = "resolved";
- }, failList.disable, progressList.lock ).fail( function() {
- state = "rejected";
- }, doneList.disable, progressList.lock );
-
- // Call given func if any
- if ( func ) {
- func.call( deferred, deferred );
- }
-
- // All done!
- return deferred;
- },
-
- // Deferred helper
- when: function( firstParam ) {
- var args = sliceDeferred.call( arguments, 0 ),
- i = 0,
- length = args.length,
- pValues = new Array( length ),
- count = length,
- pCount = length,
- deferred = length <= 1 && firstParam && jQuery.isFunction( firstParam.promise ) ?
- firstParam :
- jQuery.Deferred(),
- promise = deferred.promise();
- function resolveFunc( i ) {
- return function( value ) {
- args[ i ] = arguments.length > 1 ? sliceDeferred.call( arguments, 0 ) : value;
- if ( !( --count ) ) {
- deferred.resolveWith( deferred, args );
- }
- };
- }
- function progressFunc( i ) {
- return function( value ) {
- pValues[ i ] = arguments.length > 1 ? sliceDeferred.call( arguments, 0 ) : value;
- deferred.notifyWith( promise, pValues );
- };
- }
- if ( length > 1 ) {
- for ( ; i < length; i++ ) {
- if ( args[ i ] && args[ i ].promise && jQuery.isFunction( args[ i ].promise ) ) {
- args[ i ].promise().then( resolveFunc(i), deferred.reject, progressFunc(i) );
- } else {
- --count;
- }
- }
- if ( !count ) {
- deferred.resolveWith( deferred, args );
- }
- } else if ( deferred !== firstParam ) {
- deferred.resolveWith( deferred, length ? [ firstParam ] : [] );
- }
- return promise;
- }
-});
-
-
-
-
-jQuery.support = (function() {
-
- var support,
- all,
- a,
- select,
- opt,
- input,
- fragment,
- tds,
- events,
- eventName,
- i,
- isSupported,
- div = document.createElement( "div" ),
- documentElement = document.documentElement;
-
- // Preliminary tests
- div.setAttribute("className", "t");
- div.innerHTML = "
a";
-
- all = div.getElementsByTagName( "*" );
- a = div.getElementsByTagName( "a" )[ 0 ];
-
- // Can't get basic test support
- if ( !all || !all.length || !a ) {
- return {};
- }
-
- // First batch of supports tests
- select = document.createElement( "select" );
- opt = select.appendChild( document.createElement("option") );
- input = div.getElementsByTagName( "input" )[ 0 ];
-
- support = {
- // IE strips leading whitespace when .innerHTML is used
- leadingWhitespace: ( div.firstChild.nodeType === 3 ),
-
- // Make sure that tbody elements aren't automatically inserted
- // IE will insert them into empty tables
- tbody: !div.getElementsByTagName("tbody").length,
-
- // Make sure that link elements get serialized correctly by innerHTML
- // This requires a wrapper element in IE
- htmlSerialize: !!div.getElementsByTagName("link").length,
-
- // Get the style information from getAttribute
- // (IE uses .cssText instead)
- style: /top/.test( a.getAttribute("style") ),
-
- // Make sure that URLs aren't manipulated
- // (IE normalizes it by default)
- hrefNormalized: ( a.getAttribute("href") === "/a" ),
-
- // Make sure that element opacity exists
- // (IE uses filter instead)
- // Use a regex to work around a WebKit issue. See #5145
- opacity: /^0.55/.test( a.style.opacity ),
-
- // Verify style float existence
- // (IE uses styleFloat instead of cssFloat)
- cssFloat: !!a.style.cssFloat,
-
- // Make sure that if no value is specified for a checkbox
- // that it defaults to "on".
- // (WebKit defaults to "" instead)
- checkOn: ( input.value === "on" ),
-
- // Make sure that a selected-by-default option has a working selected property.
- // (WebKit defaults to false instead of true, IE too, if it's in an optgroup)
- optSelected: opt.selected,
-
- // Test setAttribute on camelCase class. If it works, we need attrFixes when doing get/setAttribute (ie6/7)
- getSetAttribute: div.className !== "t",
-
- // Tests for enctype support on a form(#6743)
- enctype: !!document.createElement("form").enctype,
-
- // Makes sure cloning an html5 element does not cause problems
- // Where outerHTML is undefined, this still works
- html5Clone: document.createElement("nav").cloneNode( true ).outerHTML !== "<:nav>",
-
- // Will be defined later
- submitBubbles: true,
- changeBubbles: true,
- focusinBubbles: false,
- deleteExpando: true,
- noCloneEvent: true,
- inlineBlockNeedsLayout: false,
- shrinkWrapBlocks: false,
- reliableMarginRight: true,
- pixelMargin: true
- };
-
- // jQuery.boxModel DEPRECATED in 1.3, use jQuery.support.boxModel instead
- jQuery.boxModel = support.boxModel = (document.compatMode === "CSS1Compat");
-
- // Make sure checked status is properly cloned
- input.checked = true;
- support.noCloneChecked = input.cloneNode( true ).checked;
-
- // Make sure that the options inside disabled selects aren't marked as disabled
- // (WebKit marks them as disabled)
- select.disabled = true;
- support.optDisabled = !opt.disabled;
-
- // Test to see if it's possible to delete an expando from an element
- // Fails in Internet Explorer
- try {
- delete div.test;
- } catch( e ) {
- support.deleteExpando = false;
- }
-
- if ( !div.addEventListener && div.attachEvent && div.fireEvent ) {
- div.attachEvent( "onclick", function() {
- // Cloning a node shouldn't copy over any
- // bound event handlers (IE does this)
- support.noCloneEvent = false;
- });
- div.cloneNode( true ).fireEvent( "onclick" );
- }
-
- // Check if a radio maintains its value
- // after being appended to the DOM
- input = document.createElement("input");
- input.value = "t";
- input.setAttribute("type", "radio");
- support.radioValue = input.value === "t";
-
- input.setAttribute("checked", "checked");
-
- // #11217 - WebKit loses check when the name is after the checked attribute
- input.setAttribute( "name", "t" );
-
- div.appendChild( input );
- fragment = document.createDocumentFragment();
- fragment.appendChild( div.lastChild );
-
- // WebKit doesn't clone checked state correctly in fragments
- support.checkClone = fragment.cloneNode( true ).cloneNode( true ).lastChild.checked;
-
- // Check if a disconnected checkbox will retain its checked
- // value of true after appended to the DOM (IE6/7)
- support.appendChecked = input.checked;
-
- fragment.removeChild( input );
- fragment.appendChild( div );
-
- // Technique from Juriy Zaytsev
- // http://perfectionkills.com/detecting-event-support-without-browser-sniffing/
- // We only care about the case where non-standard event systems
- // are used, namely in IE. Short-circuiting here helps us to
- // avoid an eval call (in setAttribute) which can cause CSP
- // to go haywire. See: https://developer.mozilla.org/en/Security/CSP
- if ( div.attachEvent ) {
- for ( i in {
- submit: 1,
- change: 1,
- focusin: 1
- }) {
- eventName = "on" + i;
- isSupported = ( eventName in div );
- if ( !isSupported ) {
- div.setAttribute( eventName, "return;" );
- isSupported = ( typeof div[ eventName ] === "function" );
- }
- support[ i + "Bubbles" ] = isSupported;
- }
- }
-
- fragment.removeChild( div );
-
- // Null elements to avoid leaks in IE
- fragment = select = opt = div = input = null;
-
- // Run tests that need a body at doc ready
- jQuery(function() {
- var container, outer, inner, table, td, offsetSupport,
- marginDiv, conMarginTop, style, html, positionTopLeftWidthHeight,
- paddingMarginBorderVisibility, paddingMarginBorder,
- body = document.getElementsByTagName("body")[0];
-
- if ( !body ) {
- // Return for frameset docs that don't have a body
- return;
- }
-
- conMarginTop = 1;
- paddingMarginBorder = "padding:0;margin:0;border:";
- positionTopLeftWidthHeight = "position:absolute;top:0;left:0;width:1px;height:1px;";
- paddingMarginBorderVisibility = paddingMarginBorder + "0;visibility:hidden;";
- style = "style='" + positionTopLeftWidthHeight + paddingMarginBorder + "5px solid #000;";
- html = "
" +
- "
" +
- "
";
-
- container = document.createElement("div");
- container.style.cssText = paddingMarginBorderVisibility + "width:0;height:0;position:static;top:0;margin-top:" + conMarginTop + "px";
- body.insertBefore( container, body.firstChild );
-
- // Construct the test element
- div = document.createElement("div");
- container.appendChild( div );
-
- // Check if table cells still have offsetWidth/Height when they are set
- // to display:none and there are still other visible table cells in a
- // table row; if so, offsetWidth/Height are not reliable for use when
- // determining if an element has been hidden directly using
- // display:none (it is still safe to use offsets if a parent element is
- // hidden; don safety goggles and see bug #4512 for more information).
- // (only IE 8 fails this test)
- div.innerHTML = "
t
";
- tds = div.getElementsByTagName( "td" );
- isSupported = ( tds[ 0 ].offsetHeight === 0 );
-
- tds[ 0 ].style.display = "";
- tds[ 1 ].style.display = "none";
-
- // Check if empty table cells still have offsetWidth/Height
- // (IE <= 8 fail this test)
- support.reliableHiddenOffsets = isSupported && ( tds[ 0 ].offsetHeight === 0 );
-
- // Check if div with explicit width and no margin-right incorrectly
- // gets computed margin-right based on width of container. For more
- // info see bug #3333
- // Fails in WebKit before Feb 2011 nightlies
- // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right
- if ( window.getComputedStyle ) {
- div.innerHTML = "";
- marginDiv = document.createElement( "div" );
- marginDiv.style.width = "0";
- marginDiv.style.marginRight = "0";
- div.style.width = "2px";
- div.appendChild( marginDiv );
- support.reliableMarginRight =
- ( parseInt( ( window.getComputedStyle( marginDiv, null ) || { marginRight: 0 } ).marginRight, 10 ) || 0 ) === 0;
- }
-
- if ( typeof div.style.zoom !== "undefined" ) {
- // Check if natively block-level elements act like inline-block
- // elements when setting their display to 'inline' and giving
- // them layout
- // (IE < 8 does this)
- div.innerHTML = "";
- div.style.width = div.style.padding = "1px";
- div.style.border = 0;
- div.style.overflow = "hidden";
- div.style.display = "inline";
- div.style.zoom = 1;
- support.inlineBlockNeedsLayout = ( div.offsetWidth === 3 );
-
- // Check if elements with layout shrink-wrap their children
- // (IE 6 does this)
- div.style.display = "block";
- div.style.overflow = "visible";
- div.innerHTML = "";
- support.shrinkWrapBlocks = ( div.offsetWidth !== 3 );
- }
-
- div.style.cssText = positionTopLeftWidthHeight + paddingMarginBorderVisibility;
- div.innerHTML = html;
-
- outer = div.firstChild;
- inner = outer.firstChild;
- td = outer.nextSibling.firstChild.firstChild;
-
- offsetSupport = {
- doesNotAddBorder: ( inner.offsetTop !== 5 ),
- doesAddBorderForTableAndCells: ( td.offsetTop === 5 )
- };
-
- inner.style.position = "fixed";
- inner.style.top = "20px";
-
- // safari subtracts parent border width here which is 5px
- offsetSupport.fixedPosition = ( inner.offsetTop === 20 || inner.offsetTop === 15 );
- inner.style.position = inner.style.top = "";
-
- outer.style.overflow = "hidden";
- outer.style.position = "relative";
-
- offsetSupport.subtractsBorderForOverflowNotVisible = ( inner.offsetTop === -5 );
- offsetSupport.doesNotIncludeMarginInBodyOffset = ( body.offsetTop !== conMarginTop );
-
- if ( window.getComputedStyle ) {
- div.style.marginTop = "1%";
- support.pixelMargin = ( window.getComputedStyle( div, null ) || { marginTop: 0 } ).marginTop !== "1%";
- }
-
- if ( typeof container.style.zoom !== "undefined" ) {
- container.style.zoom = 1;
- }
-
- body.removeChild( container );
- marginDiv = div = container = null;
-
- jQuery.extend( support, offsetSupport );
- });
-
- return support;
-})();
-
-
-
-
-var rbrace = /^(?:\{.*\}|\[.*\])$/,
- rmultiDash = /([A-Z])/g;
-
-jQuery.extend({
- cache: {},
-
- // Please use with caution
- uuid: 0,
-
- // Unique for each copy of jQuery on the page
- // Non-digits removed to match rinlinejQuery
- expando: "jQuery" + ( jQuery.fn.jquery + Math.random() ).replace( /\D/g, "" ),
-
- // The following elements throw uncatchable exceptions if you
- // attempt to add expando properties to them.
- noData: {
- "embed": true,
- // Ban all objects except for Flash (which handle expandos)
- "object": "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",
- "applet": true
- },
-
- hasData: function( elem ) {
- elem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ];
- return !!elem && !isEmptyDataObject( elem );
- },
-
- data: function( elem, name, data, pvt /* Internal Use Only */ ) {
- if ( !jQuery.acceptData( elem ) ) {
- return;
- }
-
- var privateCache, thisCache, ret,
- internalKey = jQuery.expando,
- getByName = typeof name === "string",
-
- // We have to handle DOM nodes and JS objects differently because IE6-7
- // can't GC object references properly across the DOM-JS boundary
- isNode = elem.nodeType,
-
- // Only DOM nodes need the global jQuery cache; JS object data is
- // attached directly to the object so GC can occur automatically
- cache = isNode ? jQuery.cache : elem,
-
- // Only defining an ID for JS objects if its cache already exists allows
- // the code to shortcut on the same path as a DOM node with no cache
- id = isNode ? elem[ internalKey ] : elem[ internalKey ] && internalKey,
- isEvents = name === "events";
-
- // Avoid doing any more work than we need to when trying to get data on an
- // object that has no data at all
- if ( (!id || !cache[id] || (!isEvents && !pvt && !cache[id].data)) && getByName && data === undefined ) {
- return;
- }
-
- if ( !id ) {
- // Only DOM nodes need a new unique ID for each element since their data
- // ends up in the global cache
- if ( isNode ) {
- elem[ internalKey ] = id = ++jQuery.uuid;
- } else {
- id = internalKey;
- }
- }
-
- if ( !cache[ id ] ) {
- cache[ id ] = {};
-
- // Avoids exposing jQuery metadata on plain JS objects when the object
- // is serialized using JSON.stringify
- if ( !isNode ) {
- cache[ id ].toJSON = jQuery.noop;
- }
- }
-
- // An object can be passed to jQuery.data instead of a key/value pair; this gets
- // shallow copied over onto the existing cache
- if ( typeof name === "object" || typeof name === "function" ) {
- if ( pvt ) {
- cache[ id ] = jQuery.extend( cache[ id ], name );
- } else {
- cache[ id ].data = jQuery.extend( cache[ id ].data, name );
- }
- }
-
- privateCache = thisCache = cache[ id ];
-
- // jQuery data() is stored in a separate object inside the object's internal data
- // cache in order to avoid key collisions between internal data and user-defined
- // data.
- if ( !pvt ) {
- if ( !thisCache.data ) {
- thisCache.data = {};
- }
-
- thisCache = thisCache.data;
- }
-
- if ( data !== undefined ) {
- thisCache[ jQuery.camelCase( name ) ] = data;
- }
-
- // Users should not attempt to inspect the internal events object using jQuery.data,
- // it is undocumented and subject to change. But does anyone listen? No.
- if ( isEvents && !thisCache[ name ] ) {
- return privateCache.events;
- }
-
- // Check for both converted-to-camel and non-converted data property names
- // If a data property was specified
- if ( getByName ) {
-
- // First Try to find as-is property data
- ret = thisCache[ name ];
-
- // Test for null|undefined property data
- if ( ret == null ) {
-
- // Try to find the camelCased property
- ret = thisCache[ jQuery.camelCase( name ) ];
- }
- } else {
- ret = thisCache;
- }
-
- return ret;
- },
-
- removeData: function( elem, name, pvt /* Internal Use Only */ ) {
- if ( !jQuery.acceptData( elem ) ) {
- return;
- }
-
- var thisCache, i, l,
-
- // Reference to internal data cache key
- internalKey = jQuery.expando,
-
- isNode = elem.nodeType,
-
- // See jQuery.data for more information
- cache = isNode ? jQuery.cache : elem,
-
- // See jQuery.data for more information
- id = isNode ? elem[ internalKey ] : internalKey;
-
- // If there is already no cache entry for this object, there is no
- // purpose in continuing
- if ( !cache[ id ] ) {
- return;
- }
-
- if ( name ) {
-
- thisCache = pvt ? cache[ id ] : cache[ id ].data;
-
- if ( thisCache ) {
-
- // Support array or space separated string names for data keys
- if ( !jQuery.isArray( name ) ) {
-
- // try the string as a key before any manipulation
- if ( name in thisCache ) {
- name = [ name ];
- } else {
-
- // split the camel cased version by spaces unless a key with the spaces exists
- name = jQuery.camelCase( name );
- if ( name in thisCache ) {
- name = [ name ];
- } else {
- name = name.split( " " );
- }
- }
- }
-
- for ( i = 0, l = name.length; i < l; i++ ) {
- delete thisCache[ name[i] ];
- }
-
- // If there is no data left in the cache, we want to continue
- // and let the cache object itself get destroyed
- if ( !( pvt ? isEmptyDataObject : jQuery.isEmptyObject )( thisCache ) ) {
- return;
- }
- }
- }
-
- // See jQuery.data for more information
- if ( !pvt ) {
- delete cache[ id ].data;
-
- // Don't destroy the parent cache unless the internal data object
- // had been the only thing left in it
- if ( !isEmptyDataObject(cache[ id ]) ) {
- return;
- }
- }
-
- // Browsers that fail expando deletion also refuse to delete expandos on
- // the window, but it will allow it on all other JS objects; other browsers
- // don't care
- // Ensure that `cache` is not a window object #10080
- if ( jQuery.support.deleteExpando || !cache.setInterval ) {
- delete cache[ id ];
- } else {
- cache[ id ] = null;
- }
-
- // We destroyed the cache and need to eliminate the expando on the node to avoid
- // false lookups in the cache for entries that no longer exist
- if ( isNode ) {
- // IE does not allow us to delete expando properties from nodes,
- // nor does it have a removeAttribute function on Document nodes;
- // we must handle all of these cases
- if ( jQuery.support.deleteExpando ) {
- delete elem[ internalKey ];
- } else if ( elem.removeAttribute ) {
- elem.removeAttribute( internalKey );
- } else {
- elem[ internalKey ] = null;
- }
- }
- },
-
- // For internal use only.
- _data: function( elem, name, data ) {
- return jQuery.data( elem, name, data, true );
- },
-
- // A method for determining if a DOM node can handle the data expando
- acceptData: function( elem ) {
- if ( elem.nodeName ) {
- var match = jQuery.noData[ elem.nodeName.toLowerCase() ];
-
- if ( match ) {
- return !(match === true || elem.getAttribute("classid") !== match);
- }
- }
-
- return true;
- }
-});
-
-jQuery.fn.extend({
- data: function( key, value ) {
- var parts, part, attr, name, l,
- elem = this[0],
- i = 0,
- data = null;
-
- // Gets all values
- if ( key === undefined ) {
- if ( this.length ) {
- data = jQuery.data( elem );
-
- if ( elem.nodeType === 1 && !jQuery._data( elem, "parsedAttrs" ) ) {
- attr = elem.attributes;
- for ( l = attr.length; i < l; i++ ) {
- name = attr[i].name;
-
- if ( name.indexOf( "data-" ) === 0 ) {
- name = jQuery.camelCase( name.substring(5) );
-
- dataAttr( elem, name, data[ name ] );
- }
- }
- jQuery._data( elem, "parsedAttrs", true );
- }
- }
-
- return data;
- }
-
- // Sets multiple values
- if ( typeof key === "object" ) {
- return this.each(function() {
- jQuery.data( this, key );
- });
- }
-
- parts = key.split( ".", 2 );
- parts[1] = parts[1] ? "." + parts[1] : "";
- part = parts[1] + "!";
-
- return jQuery.access( this, function( value ) {
-
- if ( value === undefined ) {
- data = this.triggerHandler( "getData" + part, [ parts[0] ] );
-
- // Try to fetch any internally stored data first
- if ( data === undefined && elem ) {
- data = jQuery.data( elem, key );
- data = dataAttr( elem, key, data );
- }
-
- return data === undefined && parts[1] ?
- this.data( parts[0] ) :
- data;
- }
-
- parts[1] = value;
- this.each(function() {
- var self = jQuery( this );
-
- self.triggerHandler( "setData" + part, parts );
- jQuery.data( this, key, value );
- self.triggerHandler( "changeData" + part, parts );
- });
- }, null, value, arguments.length > 1, null, false );
- },
-
- removeData: function( key ) {
- return this.each(function() {
- jQuery.removeData( this, key );
- });
- }
-});
-
-function dataAttr( elem, key, data ) {
- // If nothing was found internally, try to fetch any
- // data from the HTML5 data-* attribute
- if ( data === undefined && elem.nodeType === 1 ) {
-
- var name = "data-" + key.replace( rmultiDash, "-$1" ).toLowerCase();
-
- data = elem.getAttribute( name );
-
- if ( typeof data === "string" ) {
- try {
- data = data === "true" ? true :
- data === "false" ? false :
- data === "null" ? null :
- jQuery.isNumeric( data ) ? +data :
- rbrace.test( data ) ? jQuery.parseJSON( data ) :
- data;
- } catch( e ) {}
-
- // Make sure we set the data so it isn't changed later
- jQuery.data( elem, key, data );
-
- } else {
- data = undefined;
- }
- }
-
- return data;
-}
-
-// checks a cache object for emptiness
-function isEmptyDataObject( obj ) {
- for ( var name in obj ) {
-
- // if the public data object is empty, the private is still empty
- if ( name === "data" && jQuery.isEmptyObject( obj[name] ) ) {
- continue;
- }
- if ( name !== "toJSON" ) {
- return false;
- }
- }
-
- return true;
-}
-
-
-
-
-function handleQueueMarkDefer( elem, type, src ) {
- var deferDataKey = type + "defer",
- queueDataKey = type + "queue",
- markDataKey = type + "mark",
- defer = jQuery._data( elem, deferDataKey );
- if ( defer &&
- ( src === "queue" || !jQuery._data(elem, queueDataKey) ) &&
- ( src === "mark" || !jQuery._data(elem, markDataKey) ) ) {
- // Give room for hard-coded callbacks to fire first
- // and eventually mark/queue something else on the element
- setTimeout( function() {
- if ( !jQuery._data( elem, queueDataKey ) &&
- !jQuery._data( elem, markDataKey ) ) {
- jQuery.removeData( elem, deferDataKey, true );
- defer.fire();
- }
- }, 0 );
- }
-}
-
-jQuery.extend({
-
- _mark: function( elem, type ) {
- if ( elem ) {
- type = ( type || "fx" ) + "mark";
- jQuery._data( elem, type, (jQuery._data( elem, type ) || 0) + 1 );
- }
- },
-
- _unmark: function( force, elem, type ) {
- if ( force !== true ) {
- type = elem;
- elem = force;
- force = false;
- }
- if ( elem ) {
- type = type || "fx";
- var key = type + "mark",
- count = force ? 0 : ( (jQuery._data( elem, key ) || 1) - 1 );
- if ( count ) {
- jQuery._data( elem, key, count );
- } else {
- jQuery.removeData( elem, key, true );
- handleQueueMarkDefer( elem, type, "mark" );
- }
- }
- },
-
- queue: function( elem, type, data ) {
- var q;
- if ( elem ) {
- type = ( type || "fx" ) + "queue";
- q = jQuery._data( elem, type );
-
- // Speed up dequeue by getting out quickly if this is just a lookup
- if ( data ) {
- if ( !q || jQuery.isArray(data) ) {
- q = jQuery._data( elem, type, jQuery.makeArray(data) );
- } else {
- q.push( data );
- }
- }
- return q || [];
- }
- },
-
- dequeue: function( elem, type ) {
- type = type || "fx";
-
- var queue = jQuery.queue( elem, type ),
- fn = queue.shift(),
- hooks = {};
-
- // If the fx queue is dequeued, always remove the progress sentinel
- if ( fn === "inprogress" ) {
- fn = queue.shift();
- }
-
- if ( fn ) {
- // Add a progress sentinel to prevent the fx queue from being
- // automatically dequeued
- if ( type === "fx" ) {
- queue.unshift( "inprogress" );
- }
-
- jQuery._data( elem, type + ".run", hooks );
- fn.call( elem, function() {
- jQuery.dequeue( elem, type );
- }, hooks );
- }
-
- if ( !queue.length ) {
- jQuery.removeData( elem, type + "queue " + type + ".run", true );
- handleQueueMarkDefer( elem, type, "queue" );
- }
- }
-});
-
-jQuery.fn.extend({
- queue: function( type, data ) {
- var setter = 2;
-
- if ( typeof type !== "string" ) {
- data = type;
- type = "fx";
- setter--;
- }
-
- if ( arguments.length < setter ) {
- return jQuery.queue( this[0], type );
- }
-
- return data === undefined ?
- this :
- this.each(function() {
- var queue = jQuery.queue( this, type, data );
-
- if ( type === "fx" && queue[0] !== "inprogress" ) {
- jQuery.dequeue( this, type );
- }
- });
- },
- dequeue: function( type ) {
- return this.each(function() {
- jQuery.dequeue( this, type );
- });
- },
- // Based off of the plugin by Clint Helfers, with permission.
- // http://blindsignals.com/index.php/2009/07/jquery-delay/
- delay: function( time, type ) {
- time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time;
- type = type || "fx";
-
- return this.queue( type, function( next, hooks ) {
- var timeout = setTimeout( next, time );
- hooks.stop = function() {
- clearTimeout( timeout );
- };
- });
- },
- clearQueue: function( type ) {
- return this.queue( type || "fx", [] );
- },
- // Get a promise resolved when queues of a certain type
- // are emptied (fx is the type by default)
- promise: function( type, object ) {
- if ( typeof type !== "string" ) {
- object = type;
- type = undefined;
- }
- type = type || "fx";
- var defer = jQuery.Deferred(),
- elements = this,
- i = elements.length,
- count = 1,
- deferDataKey = type + "defer",
- queueDataKey = type + "queue",
- markDataKey = type + "mark",
- tmp;
- function resolve() {
- if ( !( --count ) ) {
- defer.resolveWith( elements, [ elements ] );
- }
- }
- while( i-- ) {
- if (( tmp = jQuery.data( elements[ i ], deferDataKey, undefined, true ) ||
- ( jQuery.data( elements[ i ], queueDataKey, undefined, true ) ||
- jQuery.data( elements[ i ], markDataKey, undefined, true ) ) &&
- jQuery.data( elements[ i ], deferDataKey, jQuery.Callbacks( "once memory" ), true ) )) {
- count++;
- tmp.add( resolve );
- }
- }
- resolve();
- return defer.promise( object );
- }
-});
-
-
-
-
-var rclass = /[\n\t\r]/g,
- rspace = /\s+/,
- rreturn = /\r/g,
- rtype = /^(?:button|input)$/i,
- rfocusable = /^(?:button|input|object|select|textarea)$/i,
- rclickable = /^a(?:rea)?$/i,
- rboolean = /^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i,
- getSetAttribute = jQuery.support.getSetAttribute,
- nodeHook, boolHook, fixSpecified;
-
-jQuery.fn.extend({
- attr: function( name, value ) {
- return jQuery.access( this, jQuery.attr, name, value, arguments.length > 1 );
- },
-
- removeAttr: function( name ) {
- return this.each(function() {
- jQuery.removeAttr( this, name );
- });
- },
-
- prop: function( name, value ) {
- return jQuery.access( this, jQuery.prop, name, value, arguments.length > 1 );
- },
-
- removeProp: function( name ) {
- name = jQuery.propFix[ name ] || name;
- return this.each(function() {
- // try/catch handles cases where IE balks (such as removing a property on window)
- try {
- this[ name ] = undefined;
- delete this[ name ];
- } catch( e ) {}
- });
- },
-
- addClass: function( value ) {
- var classNames, i, l, elem,
- setClass, c, cl;
-
- if ( jQuery.isFunction( value ) ) {
- return this.each(function( j ) {
- jQuery( this ).addClass( value.call(this, j, this.className) );
- });
- }
-
- if ( value && typeof value === "string" ) {
- classNames = value.split( rspace );
-
- for ( i = 0, l = this.length; i < l; i++ ) {
- elem = this[ i ];
-
- if ( elem.nodeType === 1 ) {
- if ( !elem.className && classNames.length === 1 ) {
- elem.className = value;
-
- } else {
- setClass = " " + elem.className + " ";
-
- for ( c = 0, cl = classNames.length; c < cl; c++ ) {
- if ( !~setClass.indexOf( " " + classNames[ c ] + " " ) ) {
- setClass += classNames[ c ] + " ";
- }
- }
- elem.className = jQuery.trim( setClass );
- }
- }
- }
- }
-
- return this;
- },
-
- removeClass: function( value ) {
- var classNames, i, l, elem, className, c, cl;
-
- if ( jQuery.isFunction( value ) ) {
- return this.each(function( j ) {
- jQuery( this ).removeClass( value.call(this, j, this.className) );
- });
- }
-
- if ( (value && typeof value === "string") || value === undefined ) {
- classNames = ( value || "" ).split( rspace );
-
- for ( i = 0, l = this.length; i < l; i++ ) {
- elem = this[ i ];
-
- if ( elem.nodeType === 1 && elem.className ) {
- if ( value ) {
- className = (" " + elem.className + " ").replace( rclass, " " );
- for ( c = 0, cl = classNames.length; c < cl; c++ ) {
- className = className.replace(" " + classNames[ c ] + " ", " ");
- }
- elem.className = jQuery.trim( className );
-
- } else {
- elem.className = "";
- }
- }
- }
- }
-
- return this;
- },
-
- toggleClass: function( value, stateVal ) {
- var type = typeof value,
- isBool = typeof stateVal === "boolean";
-
- if ( jQuery.isFunction( value ) ) {
- return this.each(function( i ) {
- jQuery( this ).toggleClass( value.call(this, i, this.className, stateVal), stateVal );
- });
- }
-
- return this.each(function() {
- if ( type === "string" ) {
- // toggle individual class names
- var className,
- i = 0,
- self = jQuery( this ),
- state = stateVal,
- classNames = value.split( rspace );
-
- while ( (className = classNames[ i++ ]) ) {
- // check each className given, space seperated list
- state = isBool ? state : !self.hasClass( className );
- self[ state ? "addClass" : "removeClass" ]( className );
- }
-
- } else if ( type === "undefined" || type === "boolean" ) {
- if ( this.className ) {
- // store className if set
- jQuery._data( this, "__className__", this.className );
- }
-
- // toggle whole className
- this.className = this.className || value === false ? "" : jQuery._data( this, "__className__" ) || "";
- }
- });
- },
-
- hasClass: function( selector ) {
- var className = " " + selector + " ",
- i = 0,
- l = this.length;
- for ( ; i < l; i++ ) {
- if ( this[i].nodeType === 1 && (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) > -1 ) {
- return true;
- }
- }
-
- return false;
- },
-
- val: function( value ) {
- var hooks, ret, isFunction,
- elem = this[0];
-
- if ( !arguments.length ) {
- if ( elem ) {
- hooks = jQuery.valHooks[ elem.type ] || jQuery.valHooks[ elem.nodeName.toLowerCase() ];
-
- if ( hooks && "get" in hooks && (ret = hooks.get( elem, "value" )) !== undefined ) {
- return ret;
- }
-
- ret = elem.value;
-
- return typeof ret === "string" ?
- // handle most common string cases
- ret.replace(rreturn, "") :
- // handle cases where value is null/undef or number
- ret == null ? "" : ret;
- }
-
- return;
- }
-
- isFunction = jQuery.isFunction( value );
-
- return this.each(function( i ) {
- var self = jQuery(this), val;
-
- if ( this.nodeType !== 1 ) {
- return;
- }
-
- if ( isFunction ) {
- val = value.call( this, i, self.val() );
- } else {
- val = value;
- }
-
- // Treat null/undefined as ""; convert numbers to string
- if ( val == null ) {
- val = "";
- } else if ( typeof val === "number" ) {
- val += "";
- } else if ( jQuery.isArray( val ) ) {
- val = jQuery.map(val, function ( value ) {
- return value == null ? "" : value + "";
- });
- }
-
- hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ];
-
- // If set returns undefined, fall back to normal setting
- if ( !hooks || !("set" in hooks) || hooks.set( this, val, "value" ) === undefined ) {
- this.value = val;
- }
- });
- }
-});
-
-jQuery.extend({
- valHooks: {
- option: {
- get: function( elem ) {
- // attributes.value is undefined in Blackberry 4.7 but
- // uses .value. See #6932
- var val = elem.attributes.value;
- return !val || val.specified ? elem.value : elem.text;
- }
- },
- select: {
- get: function( elem ) {
- var value, i, max, option,
- index = elem.selectedIndex,
- values = [],
- options = elem.options,
- one = elem.type === "select-one";
-
- // Nothing was selected
- if ( index < 0 ) {
- return null;
- }
-
- // Loop through all the selected options
- i = one ? index : 0;
- max = one ? index + 1 : options.length;
- for ( ; i < max; i++ ) {
- option = options[ i ];
-
- // Don't return options that are disabled or in a disabled optgroup
- if ( option.selected && (jQuery.support.optDisabled ? !option.disabled : option.getAttribute("disabled") === null) &&
- (!option.parentNode.disabled || !jQuery.nodeName( option.parentNode, "optgroup" )) ) {
-
- // Get the specific value for the option
- value = jQuery( option ).val();
-
- // We don't need an array for one selects
- if ( one ) {
- return value;
- }
-
- // Multi-Selects return an array
- values.push( value );
- }
- }
-
- // Fixes Bug #2551 -- select.val() broken in IE after form.reset()
- if ( one && !values.length && options.length ) {
- return jQuery( options[ index ] ).val();
- }
-
- return values;
- },
-
- set: function( elem, value ) {
- var values = jQuery.makeArray( value );
-
- jQuery(elem).find("option").each(function() {
- this.selected = jQuery.inArray( jQuery(this).val(), values ) >= 0;
- });
-
- if ( !values.length ) {
- elem.selectedIndex = -1;
- }
- return values;
- }
- }
- },
-
- attrFn: {
- val: true,
- css: true,
- html: true,
- text: true,
- data: true,
- width: true,
- height: true,
- offset: true
- },
-
- attr: function( elem, name, value, pass ) {
- var ret, hooks, notxml,
- nType = elem.nodeType;
-
- // don't get/set attributes on text, comment and attribute nodes
- if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {
- return;
- }
-
- if ( pass && name in jQuery.attrFn ) {
- return jQuery( elem )[ name ]( value );
- }
-
- // Fallback to prop when attributes are not supported
- if ( typeof elem.getAttribute === "undefined" ) {
- return jQuery.prop( elem, name, value );
- }
-
- notxml = nType !== 1 || !jQuery.isXMLDoc( elem );
-
- // All attributes are lowercase
- // Grab necessary hook if one is defined
- if ( notxml ) {
- name = name.toLowerCase();
- hooks = jQuery.attrHooks[ name ] || ( rboolean.test( name ) ? boolHook : nodeHook );
- }
-
- if ( value !== undefined ) {
-
- if ( value === null ) {
- jQuery.removeAttr( elem, name );
- return;
-
- } else if ( hooks && "set" in hooks && notxml && (ret = hooks.set( elem, value, name )) !== undefined ) {
- return ret;
-
- } else {
- elem.setAttribute( name, "" + value );
- return value;
- }
-
- } else if ( hooks && "get" in hooks && notxml && (ret = hooks.get( elem, name )) !== null ) {
- return ret;
-
- } else {
-
- ret = elem.getAttribute( name );
-
- // Non-existent attributes return null, we normalize to undefined
- return ret === null ?
- undefined :
- ret;
- }
- },
-
- removeAttr: function( elem, value ) {
- var propName, attrNames, name, l, isBool,
- i = 0;
-
- if ( value && elem.nodeType === 1 ) {
- attrNames = value.toLowerCase().split( rspace );
- l = attrNames.length;
-
- for ( ; i < l; i++ ) {
- name = attrNames[ i ];
-
- if ( name ) {
- propName = jQuery.propFix[ name ] || name;
- isBool = rboolean.test( name );
-
- // See #9699 for explanation of this approach (setting first, then removal)
- // Do not do this for boolean attributes (see #10870)
- if ( !isBool ) {
- jQuery.attr( elem, name, "" );
- }
- elem.removeAttribute( getSetAttribute ? name : propName );
-
- // Set corresponding property to false for boolean attributes
- if ( isBool && propName in elem ) {
- elem[ propName ] = false;
- }
- }
- }
- }
- },
-
- attrHooks: {
- type: {
- set: function( elem, value ) {
- // We can't allow the type property to be changed (since it causes problems in IE)
- if ( rtype.test( elem.nodeName ) && elem.parentNode ) {
- jQuery.error( "type property can't be changed" );
- } else if ( !jQuery.support.radioValue && value === "radio" && jQuery.nodeName(elem, "input") ) {
- // Setting the type on a radio button after the value resets the value in IE6-9
- // Reset value to it's default in case type is set after value
- // This is for element creation
- var val = elem.value;
- elem.setAttribute( "type", value );
- if ( val ) {
- elem.value = val;
- }
- return value;
- }
- }
- },
- // Use the value property for back compat
- // Use the nodeHook for button elements in IE6/7 (#1954)
- value: {
- get: function( elem, name ) {
- if ( nodeHook && jQuery.nodeName( elem, "button" ) ) {
- return nodeHook.get( elem, name );
- }
- return name in elem ?
- elem.value :
- null;
- },
- set: function( elem, value, name ) {
- if ( nodeHook && jQuery.nodeName( elem, "button" ) ) {
- return nodeHook.set( elem, value, name );
- }
- // Does not return so that setAttribute is also used
- elem.value = value;
- }
- }
- },
-
- propFix: {
- tabindex: "tabIndex",
- readonly: "readOnly",
- "for": "htmlFor",
- "class": "className",
- maxlength: "maxLength",
- cellspacing: "cellSpacing",
- cellpadding: "cellPadding",
- rowspan: "rowSpan",
- colspan: "colSpan",
- usemap: "useMap",
- frameborder: "frameBorder",
- contenteditable: "contentEditable"
- },
-
- prop: function( elem, name, value ) {
- var ret, hooks, notxml,
- nType = elem.nodeType;
-
- // don't get/set properties on text, comment and attribute nodes
- if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {
- return;
- }
-
- notxml = nType !== 1 || !jQuery.isXMLDoc( elem );
-
- if ( notxml ) {
- // Fix name and attach hooks
- name = jQuery.propFix[ name ] || name;
- hooks = jQuery.propHooks[ name ];
- }
-
- if ( value !== undefined ) {
- if ( hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) {
- return ret;
-
- } else {
- return ( elem[ name ] = value );
- }
-
- } else {
- if ( hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ) {
- return ret;
-
- } else {
- return elem[ name ];
- }
- }
- },
-
- propHooks: {
- tabIndex: {
- get: function( elem ) {
- // elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set
- // http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/
- var attributeNode = elem.getAttributeNode("tabindex");
-
- return attributeNode && attributeNode.specified ?
- parseInt( attributeNode.value, 10 ) :
- rfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ?
- 0 :
- undefined;
- }
- }
- }
-});
-
-// Add the tabIndex propHook to attrHooks for back-compat (different case is intentional)
-jQuery.attrHooks.tabindex = jQuery.propHooks.tabIndex;
-
-// Hook for boolean attributes
-boolHook = {
- get: function( elem, name ) {
- // Align boolean attributes with corresponding properties
- // Fall back to attribute presence where some booleans are not supported
- var attrNode,
- property = jQuery.prop( elem, name );
- return property === true || typeof property !== "boolean" && ( attrNode = elem.getAttributeNode(name) ) && attrNode.nodeValue !== false ?
- name.toLowerCase() :
- undefined;
- },
- set: function( elem, value, name ) {
- var propName;
- if ( value === false ) {
- // Remove boolean attributes when set to false
- jQuery.removeAttr( elem, name );
- } else {
- // value is true since we know at this point it's type boolean and not false
- // Set boolean attributes to the same name and set the DOM property
- propName = jQuery.propFix[ name ] || name;
- if ( propName in elem ) {
- // Only set the IDL specifically if it already exists on the element
- elem[ propName ] = true;
- }
-
- elem.setAttribute( name, name.toLowerCase() );
- }
- return name;
- }
-};
-
-// IE6/7 do not support getting/setting some attributes with get/setAttribute
-if ( !getSetAttribute ) {
-
- fixSpecified = {
- name: true,
- id: true,
- coords: true
- };
-
- // Use this for any attribute in IE6/7
- // This fixes almost every IE6/7 issue
- nodeHook = jQuery.valHooks.button = {
- get: function( elem, name ) {
- var ret;
- ret = elem.getAttributeNode( name );
- return ret && ( fixSpecified[ name ] ? ret.nodeValue !== "" : ret.specified ) ?
- ret.nodeValue :
- undefined;
- },
- set: function( elem, value, name ) {
- // Set the existing or create a new attribute node
- var ret = elem.getAttributeNode( name );
- if ( !ret ) {
- ret = document.createAttribute( name );
- elem.setAttributeNode( ret );
- }
- return ( ret.nodeValue = value + "" );
- }
- };
-
- // Apply the nodeHook to tabindex
- jQuery.attrHooks.tabindex.set = nodeHook.set;
-
- // Set width and height to auto instead of 0 on empty string( Bug #8150 )
- // This is for removals
- jQuery.each([ "width", "height" ], function( i, name ) {
- jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], {
- set: function( elem, value ) {
- if ( value === "" ) {
- elem.setAttribute( name, "auto" );
- return value;
- }
- }
- });
- });
-
- // Set contenteditable to false on removals(#10429)
- // Setting to empty string throws an error as an invalid value
- jQuery.attrHooks.contenteditable = {
- get: nodeHook.get,
- set: function( elem, value, name ) {
- if ( value === "" ) {
- value = "false";
- }
- nodeHook.set( elem, value, name );
- }
- };
-}
-
-
-// Some attributes require a special call on IE
-if ( !jQuery.support.hrefNormalized ) {
- jQuery.each([ "href", "src", "width", "height" ], function( i, name ) {
- jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], {
- get: function( elem ) {
- var ret = elem.getAttribute( name, 2 );
- return ret === null ? undefined : ret;
- }
- });
- });
-}
-
-if ( !jQuery.support.style ) {
- jQuery.attrHooks.style = {
- get: function( elem ) {
- // Return undefined in the case of empty string
- // Normalize to lowercase since IE uppercases css property names
- return elem.style.cssText.toLowerCase() || undefined;
- },
- set: function( elem, value ) {
- return ( elem.style.cssText = "" + value );
- }
- };
-}
-
-// Safari mis-reports the default selected property of an option
-// Accessing the parent's selectedIndex property fixes it
-if ( !jQuery.support.optSelected ) {
- jQuery.propHooks.selected = jQuery.extend( jQuery.propHooks.selected, {
- get: function( elem ) {
- var parent = elem.parentNode;
-
- if ( parent ) {
- parent.selectedIndex;
-
- // Make sure that it also works with optgroups, see #5701
- if ( parent.parentNode ) {
- parent.parentNode.selectedIndex;
- }
- }
- return null;
- }
- });
-}
-
-// IE6/7 call enctype encoding
-if ( !jQuery.support.enctype ) {
- jQuery.propFix.enctype = "encoding";
-}
-
-// Radios and checkboxes getter/setter
-if ( !jQuery.support.checkOn ) {
- jQuery.each([ "radio", "checkbox" ], function() {
- jQuery.valHooks[ this ] = {
- get: function( elem ) {
- // Handle the case where in Webkit "" is returned instead of "on" if a value isn't specified
- return elem.getAttribute("value") === null ? "on" : elem.value;
- }
- };
- });
-}
-jQuery.each([ "radio", "checkbox" ], function() {
- jQuery.valHooks[ this ] = jQuery.extend( jQuery.valHooks[ this ], {
- set: function( elem, value ) {
- if ( jQuery.isArray( value ) ) {
- return ( elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0 );
- }
- }
- });
-});
-
-
-
-
-var rformElems = /^(?:textarea|input|select)$/i,
- rtypenamespace = /^([^\.]*)?(?:\.(.+))?$/,
- rhoverHack = /(?:^|\s)hover(\.\S+)?\b/,
- rkeyEvent = /^key/,
- rmouseEvent = /^(?:mouse|contextmenu)|click/,
- rfocusMorph = /^(?:focusinfocus|focusoutblur)$/,
- rquickIs = /^(\w*)(?:#([\w\-]+))?(?:\.([\w\-]+))?$/,
- quickParse = function( selector ) {
- var quick = rquickIs.exec( selector );
- if ( quick ) {
- // 0 1 2 3
- // [ _, tag, id, class ]
- quick[1] = ( quick[1] || "" ).toLowerCase();
- quick[3] = quick[3] && new RegExp( "(?:^|\\s)" + quick[3] + "(?:\\s|$)" );
- }
- return quick;
- },
- quickIs = function( elem, m ) {
- var attrs = elem.attributes || {};
- return (
- (!m[1] || elem.nodeName.toLowerCase() === m[1]) &&
- (!m[2] || (attrs.id || {}).value === m[2]) &&
- (!m[3] || m[3].test( (attrs[ "class" ] || {}).value ))
- );
- },
- hoverHack = function( events ) {
- return jQuery.event.special.hover ? events : events.replace( rhoverHack, "mouseenter$1 mouseleave$1" );
- };
-
-/*
- * Helper functions for managing events -- not part of the public interface.
- * Props to Dean Edwards' addEvent library for many of the ideas.
- */
-jQuery.event = {
-
- add: function( elem, types, handler, data, selector ) {
-
- var elemData, eventHandle, events,
- t, tns, type, namespaces, handleObj,
- handleObjIn, quick, handlers, special;
-
- // Don't attach events to noData or text/comment nodes (allow plain objects tho)
- if ( elem.nodeType === 3 || elem.nodeType === 8 || !types || !handler || !(elemData = jQuery._data( elem )) ) {
- return;
- }
-
- // Caller can pass in an object of custom data in lieu of the handler
- if ( handler.handler ) {
- handleObjIn = handler;
- handler = handleObjIn.handler;
- selector = handleObjIn.selector;
- }
-
- // Make sure that the handler has a unique ID, used to find/remove it later
- if ( !handler.guid ) {
- handler.guid = jQuery.guid++;
- }
-
- // Init the element's event structure and main handler, if this is the first
- events = elemData.events;
- if ( !events ) {
- elemData.events = events = {};
- }
- eventHandle = elemData.handle;
- if ( !eventHandle ) {
- elemData.handle = eventHandle = function( e ) {
- // Discard the second event of a jQuery.event.trigger() and
- // when an event is called after a page has unloaded
- return typeof jQuery !== "undefined" && (!e || jQuery.event.triggered !== e.type) ?
- jQuery.event.dispatch.apply( eventHandle.elem, arguments ) :
- undefined;
- };
- // Add elem as a property of the handle fn to prevent a memory leak with IE non-native events
- eventHandle.elem = elem;
- }
-
- // Handle multiple events separated by a space
- // jQuery(...).bind("mouseover mouseout", fn);
- types = jQuery.trim( hoverHack(types) ).split( " " );
- for ( t = 0; t < types.length; t++ ) {
-
- tns = rtypenamespace.exec( types[t] ) || [];
- type = tns[1];
- namespaces = ( tns[2] || "" ).split( "." ).sort();
-
- // If event changes its type, use the special event handlers for the changed type
- special = jQuery.event.special[ type ] || {};
-
- // If selector defined, determine special event api type, otherwise given type
- type = ( selector ? special.delegateType : special.bindType ) || type;
-
- // Update special based on newly reset type
- special = jQuery.event.special[ type ] || {};
-
- // handleObj is passed to all event handlers
- handleObj = jQuery.extend({
- type: type,
- origType: tns[1],
- data: data,
- handler: handler,
- guid: handler.guid,
- selector: selector,
- quick: selector && quickParse( selector ),
- namespace: namespaces.join(".")
- }, handleObjIn );
-
- // Init the event handler queue if we're the first
- handlers = events[ type ];
- if ( !handlers ) {
- handlers = events[ type ] = [];
- handlers.delegateCount = 0;
-
- // Only use addEventListener/attachEvent if the special events handler returns false
- if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) {
- // Bind the global event handler to the element
- if ( elem.addEventListener ) {
- elem.addEventListener( type, eventHandle, false );
-
- } else if ( elem.attachEvent ) {
- elem.attachEvent( "on" + type, eventHandle );
- }
- }
- }
-
- if ( special.add ) {
- special.add.call( elem, handleObj );
-
- if ( !handleObj.handler.guid ) {
- handleObj.handler.guid = handler.guid;
- }
- }
-
- // Add to the element's handler list, delegates in front
- if ( selector ) {
- handlers.splice( handlers.delegateCount++, 0, handleObj );
- } else {
- handlers.push( handleObj );
- }
-
- // Keep track of which events have ever been used, for event optimization
- jQuery.event.global[ type ] = true;
- }
-
- // Nullify elem to prevent memory leaks in IE
- elem = null;
- },
-
- global: {},
-
- // Detach an event or set of events from an element
- remove: function( elem, types, handler, selector, mappedTypes ) {
-
- var elemData = jQuery.hasData( elem ) && jQuery._data( elem ),
- t, tns, type, origType, namespaces, origCount,
- j, events, special, handle, eventType, handleObj;
-
- if ( !elemData || !(events = elemData.events) ) {
- return;
- }
-
- // Once for each type.namespace in types; type may be omitted
- types = jQuery.trim( hoverHack( types || "" ) ).split(" ");
- for ( t = 0; t < types.length; t++ ) {
- tns = rtypenamespace.exec( types[t] ) || [];
- type = origType = tns[1];
- namespaces = tns[2];
-
- // Unbind all events (on this namespace, if provided) for the element
- if ( !type ) {
- for ( type in events ) {
- jQuery.event.remove( elem, type + types[ t ], handler, selector, true );
- }
- continue;
- }
-
- special = jQuery.event.special[ type ] || {};
- type = ( selector? special.delegateType : special.bindType ) || type;
- eventType = events[ type ] || [];
- origCount = eventType.length;
- namespaces = namespaces ? new RegExp("(^|\\.)" + namespaces.split(".").sort().join("\\.(?:.*\\.)?") + "(\\.|$)") : null;
-
- // Remove matching events
- for ( j = 0; j < eventType.length; j++ ) {
- handleObj = eventType[ j ];
-
- if ( ( mappedTypes || origType === handleObj.origType ) &&
- ( !handler || handler.guid === handleObj.guid ) &&
- ( !namespaces || namespaces.test( handleObj.namespace ) ) &&
- ( !selector || selector === handleObj.selector || selector === "**" && handleObj.selector ) ) {
- eventType.splice( j--, 1 );
-
- if ( handleObj.selector ) {
- eventType.delegateCount--;
- }
- if ( special.remove ) {
- special.remove.call( elem, handleObj );
- }
- }
- }
-
- // Remove generic event handler if we removed something and no more handlers exist
- // (avoids potential for endless recursion during removal of special event handlers)
- if ( eventType.length === 0 && origCount !== eventType.length ) {
- if ( !special.teardown || special.teardown.call( elem, namespaces ) === false ) {
- jQuery.removeEvent( elem, type, elemData.handle );
- }
-
- delete events[ type ];
- }
- }
-
- // Remove the expando if it's no longer used
- if ( jQuery.isEmptyObject( events ) ) {
- handle = elemData.handle;
- if ( handle ) {
- handle.elem = null;
- }
-
- // removeData also checks for emptiness and clears the expando if empty
- // so use it instead of delete
- jQuery.removeData( elem, [ "events", "handle" ], true );
- }
- },
-
- // Events that are safe to short-circuit if no handlers are attached.
- // Native DOM events should not be added, they may have inline handlers.
- customEvent: {
- "getData": true,
- "setData": true,
- "changeData": true
- },
-
- trigger: function( event, data, elem, onlyHandlers ) {
- // Don't do events on text and comment nodes
- if ( elem && (elem.nodeType === 3 || elem.nodeType === 8) ) {
- return;
- }
-
- // Event object or event type
- var type = event.type || event,
- namespaces = [],
- cache, exclusive, i, cur, old, ontype, special, handle, eventPath, bubbleType;
-
- // focus/blur morphs to focusin/out; ensure we're not firing them right now
- if ( rfocusMorph.test( type + jQuery.event.triggered ) ) {
- return;
- }
-
- if ( type.indexOf( "!" ) >= 0 ) {
- // Exclusive events trigger only for the exact event (no namespaces)
- type = type.slice(0, -1);
- exclusive = true;
- }
-
- if ( type.indexOf( "." ) >= 0 ) {
- // Namespaced trigger; create a regexp to match event type in handle()
- namespaces = type.split(".");
- type = namespaces.shift();
- namespaces.sort();
- }
-
- if ( (!elem || jQuery.event.customEvent[ type ]) && !jQuery.event.global[ type ] ) {
- // No jQuery handlers for this event type, and it can't have inline handlers
- return;
- }
-
- // Caller can pass in an Event, Object, or just an event type string
- event = typeof event === "object" ?
- // jQuery.Event object
- event[ jQuery.expando ] ? event :
- // Object literal
- new jQuery.Event( type, event ) :
- // Just the event type (string)
- new jQuery.Event( type );
-
- event.type = type;
- event.isTrigger = true;
- event.exclusive = exclusive;
- event.namespace = namespaces.join( "." );
- event.namespace_re = event.namespace? new RegExp("(^|\\.)" + namespaces.join("\\.(?:.*\\.)?") + "(\\.|$)") : null;
- ontype = type.indexOf( ":" ) < 0 ? "on" + type : "";
-
- // Handle a global trigger
- if ( !elem ) {
-
- // TODO: Stop taunting the data cache; remove global events and always attach to document
- cache = jQuery.cache;
- for ( i in cache ) {
- if ( cache[ i ].events && cache[ i ].events[ type ] ) {
- jQuery.event.trigger( event, data, cache[ i ].handle.elem, true );
- }
- }
- return;
- }
-
- // Clean up the event in case it is being reused
- event.result = undefined;
- if ( !event.target ) {
- event.target = elem;
- }
-
- // Clone any incoming data and prepend the event, creating the handler arg list
- data = data != null ? jQuery.makeArray( data ) : [];
- data.unshift( event );
-
- // Allow special events to draw outside the lines
- special = jQuery.event.special[ type ] || {};
- if ( special.trigger && special.trigger.apply( elem, data ) === false ) {
- return;
- }
-
- // Determine event propagation path in advance, per W3C events spec (#9951)
- // Bubble up to document, then to window; watch for a global ownerDocument var (#9724)
- eventPath = [[ elem, special.bindType || type ]];
- if ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) {
-
- bubbleType = special.delegateType || type;
- cur = rfocusMorph.test( bubbleType + type ) ? elem : elem.parentNode;
- old = null;
- for ( ; cur; cur = cur.parentNode ) {
- eventPath.push([ cur, bubbleType ]);
- old = cur;
- }
-
- // Only add window if we got to document (e.g., not plain obj or detached DOM)
- if ( old && old === elem.ownerDocument ) {
- eventPath.push([ old.defaultView || old.parentWindow || window, bubbleType ]);
- }
- }
-
- // Fire handlers on the event path
- for ( i = 0; i < eventPath.length && !event.isPropagationStopped(); i++ ) {
-
- cur = eventPath[i][0];
- event.type = eventPath[i][1];
-
- handle = ( jQuery._data( cur, "events" ) || {} )[ event.type ] && jQuery._data( cur, "handle" );
- if ( handle ) {
- handle.apply( cur, data );
- }
- // Note that this is a bare JS function and not a jQuery handler
- handle = ontype && cur[ ontype ];
- if ( handle && jQuery.acceptData( cur ) && handle.apply( cur, data ) === false ) {
- event.preventDefault();
- }
- }
- event.type = type;
-
- // If nobody prevented the default action, do it now
- if ( !onlyHandlers && !event.isDefaultPrevented() ) {
-
- if ( (!special._default || special._default.apply( elem.ownerDocument, data ) === false) &&
- !(type === "click" && jQuery.nodeName( elem, "a" )) && jQuery.acceptData( elem ) ) {
-
- // Call a native DOM method on the target with the same name name as the event.
- // Can't use an .isFunction() check here because IE6/7 fails that test.
- // Don't do default actions on window, that's where global variables be (#6170)
- // IE<9 dies on focus/blur to hidden element (#1486)
- if ( ontype && elem[ type ] && ((type !== "focus" && type !== "blur") || event.target.offsetWidth !== 0) && !jQuery.isWindow( elem ) ) {
-
- // Don't re-trigger an onFOO event when we call its FOO() method
- old = elem[ ontype ];
-
- if ( old ) {
- elem[ ontype ] = null;
- }
-
- // Prevent re-triggering of the same event, since we already bubbled it above
- jQuery.event.triggered = type;
- elem[ type ]();
- jQuery.event.triggered = undefined;
-
- if ( old ) {
- elem[ ontype ] = old;
- }
- }
- }
- }
-
- return event.result;
- },
-
- dispatch: function( event ) {
-
- // Make a writable jQuery.Event from the native event object
- event = jQuery.event.fix( event || window.event );
-
- var handlers = ( (jQuery._data( this, "events" ) || {} )[ event.type ] || []),
- delegateCount = handlers.delegateCount,
- args = [].slice.call( arguments, 0 ),
- run_all = !event.exclusive && !event.namespace,
- special = jQuery.event.special[ event.type ] || {},
- handlerQueue = [],
- i, j, cur, jqcur, ret, selMatch, matched, matches, handleObj, sel, related;
-
- // Use the fix-ed jQuery.Event rather than the (read-only) native event
- args[0] = event;
- event.delegateTarget = this;
-
- // Call the preDispatch hook for the mapped type, and let it bail if desired
- if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) {
- return;
- }
-
- // Determine handlers that should run if there are delegated events
- // Avoid non-left-click bubbling in Firefox (#3861)
- if ( delegateCount && !(event.button && event.type === "click") ) {
-
- // Pregenerate a single jQuery object for reuse with .is()
- jqcur = jQuery(this);
- jqcur.context = this.ownerDocument || this;
-
- for ( cur = event.target; cur != this; cur = cur.parentNode || this ) {
-
- // Don't process events on disabled elements (#6911, #8165)
- if ( cur.disabled !== true ) {
- selMatch = {};
- matches = [];
- jqcur[0] = cur;
- for ( i = 0; i < delegateCount; i++ ) {
- handleObj = handlers[ i ];
- sel = handleObj.selector;
-
- if ( selMatch[ sel ] === undefined ) {
- selMatch[ sel ] = (
- handleObj.quick ? quickIs( cur, handleObj.quick ) : jqcur.is( sel )
- );
- }
- if ( selMatch[ sel ] ) {
- matches.push( handleObj );
- }
- }
- if ( matches.length ) {
- handlerQueue.push({ elem: cur, matches: matches });
- }
- }
- }
- }
-
- // Add the remaining (directly-bound) handlers
- if ( handlers.length > delegateCount ) {
- handlerQueue.push({ elem: this, matches: handlers.slice( delegateCount ) });
- }
-
- // Run delegates first; they may want to stop propagation beneath us
- for ( i = 0; i < handlerQueue.length && !event.isPropagationStopped(); i++ ) {
- matched = handlerQueue[ i ];
- event.currentTarget = matched.elem;
-
- for ( j = 0; j < matched.matches.length && !event.isImmediatePropagationStopped(); j++ ) {
- handleObj = matched.matches[ j ];
-
- // Triggered event must either 1) be non-exclusive and have no namespace, or
- // 2) have namespace(s) a subset or equal to those in the bound event (both can have no namespace).
- if ( run_all || (!event.namespace && !handleObj.namespace) || event.namespace_re && event.namespace_re.test( handleObj.namespace ) ) {
-
- event.data = handleObj.data;
- event.handleObj = handleObj;
-
- ret = ( (jQuery.event.special[ handleObj.origType ] || {}).handle || handleObj.handler )
- .apply( matched.elem, args );
-
- if ( ret !== undefined ) {
- event.result = ret;
- if ( ret === false ) {
- event.preventDefault();
- event.stopPropagation();
- }
- }
- }
- }
- }
-
- // Call the postDispatch hook for the mapped type
- if ( special.postDispatch ) {
- special.postDispatch.call( this, event );
- }
-
- return event.result;
- },
-
- // Includes some event props shared by KeyEvent and MouseEvent
- // *** attrChange attrName relatedNode srcElement are not normalized, non-W3C, deprecated, will be removed in 1.8 ***
- props: "attrChange attrName relatedNode srcElement altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),
-
- fixHooks: {},
-
- keyHooks: {
- props: "char charCode key keyCode".split(" "),
- filter: function( event, original ) {
-
- // Add which for key events
- if ( event.which == null ) {
- event.which = original.charCode != null ? original.charCode : original.keyCode;
- }
-
- return event;
- }
- },
-
- mouseHooks: {
- props: "button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),
- filter: function( event, original ) {
- var eventDoc, doc, body,
- button = original.button,
- fromElement = original.fromElement;
-
- // Calculate pageX/Y if missing and clientX/Y available
- if ( event.pageX == null && original.clientX != null ) {
- eventDoc = event.target.ownerDocument || document;
- doc = eventDoc.documentElement;
- body = eventDoc.body;
-
- event.pageX = original.clientX + ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) - ( doc && doc.clientLeft || body && body.clientLeft || 0 );
- event.pageY = original.clientY + ( doc && doc.scrollTop || body && body.scrollTop || 0 ) - ( doc && doc.clientTop || body && body.clientTop || 0 );
- }
-
- // Add relatedTarget, if necessary
- if ( !event.relatedTarget && fromElement ) {
- event.relatedTarget = fromElement === event.target ? original.toElement : fromElement;
- }
-
- // Add which for click: 1 === left; 2 === middle; 3 === right
- // Note: button is not normalized, so don't use it
- if ( !event.which && button !== undefined ) {
- event.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) );
- }
-
- return event;
- }
- },
-
- fix: function( event ) {
- if ( event[ jQuery.expando ] ) {
- return event;
- }
-
- // Create a writable copy of the event object and normalize some properties
- var i, prop,
- originalEvent = event,
- fixHook = jQuery.event.fixHooks[ event.type ] || {},
- copy = fixHook.props ? this.props.concat( fixHook.props ) : this.props;
-
- event = jQuery.Event( originalEvent );
-
- for ( i = copy.length; i; ) {
- prop = copy[ --i ];
- event[ prop ] = originalEvent[ prop ];
- }
-
- // Fix target property, if necessary (#1925, IE 6/7/8 & Safari2)
- if ( !event.target ) {
- event.target = originalEvent.srcElement || document;
- }
-
- // Target should not be a text node (#504, Safari)
- if ( event.target.nodeType === 3 ) {
- event.target = event.target.parentNode;
- }
-
- // For mouse/key events; add metaKey if it's not there (#3368, IE6/7/8)
- if ( event.metaKey === undefined ) {
- event.metaKey = event.ctrlKey;
- }
-
- return fixHook.filter? fixHook.filter( event, originalEvent ) : event;
- },
-
- special: {
- ready: {
- // Make sure the ready event is setup
- setup: jQuery.bindReady
- },
-
- load: {
- // Prevent triggered image.load events from bubbling to window.load
- noBubble: true
- },
-
- focus: {
- delegateType: "focusin"
- },
- blur: {
- delegateType: "focusout"
- },
-
- beforeunload: {
- setup: function( data, namespaces, eventHandle ) {
- // We only want to do this special case on windows
- if ( jQuery.isWindow( this ) ) {
- this.onbeforeunload = eventHandle;
- }
- },
-
- teardown: function( namespaces, eventHandle ) {
- if ( this.onbeforeunload === eventHandle ) {
- this.onbeforeunload = null;
- }
- }
- }
- },
-
- simulate: function( type, elem, event, bubble ) {
- // Piggyback on a donor event to simulate a different one.
- // Fake originalEvent to avoid donor's stopPropagation, but if the
- // simulated event prevents default then we do the same on the donor.
- var e = jQuery.extend(
- new jQuery.Event(),
- event,
- { type: type,
- isSimulated: true,
- originalEvent: {}
- }
- );
- if ( bubble ) {
- jQuery.event.trigger( e, null, elem );
- } else {
- jQuery.event.dispatch.call( elem, e );
- }
- if ( e.isDefaultPrevented() ) {
- event.preventDefault();
- }
- }
-};
-
-// Some plugins are using, but it's undocumented/deprecated and will be removed.
-// The 1.7 special event interface should provide all the hooks needed now.
-jQuery.event.handle = jQuery.event.dispatch;
-
-jQuery.removeEvent = document.removeEventListener ?
- function( elem, type, handle ) {
- if ( elem.removeEventListener ) {
- elem.removeEventListener( type, handle, false );
- }
- } :
- function( elem, type, handle ) {
- if ( elem.detachEvent ) {
- elem.detachEvent( "on" + type, handle );
- }
- };
-
-jQuery.Event = function( src, props ) {
- // Allow instantiation without the 'new' keyword
- if ( !(this instanceof jQuery.Event) ) {
- return new jQuery.Event( src, props );
- }
-
- // Event object
- if ( src && src.type ) {
- this.originalEvent = src;
- this.type = src.type;
-
- // Events bubbling up the document may have been marked as prevented
- // by a handler lower down the tree; reflect the correct value.
- this.isDefaultPrevented = ( src.defaultPrevented || src.returnValue === false ||
- src.getPreventDefault && src.getPreventDefault() ) ? returnTrue : returnFalse;
-
- // Event type
- } else {
- this.type = src;
- }
-
- // Put explicitly provided properties onto the event object
- if ( props ) {
- jQuery.extend( this, props );
- }
-
- // Create a timestamp if incoming event doesn't have one
- this.timeStamp = src && src.timeStamp || jQuery.now();
-
- // Mark it as fixed
- this[ jQuery.expando ] = true;
-};
-
-function returnFalse() {
- return false;
-}
-function returnTrue() {
- return true;
-}
-
-// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding
-// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html
-jQuery.Event.prototype = {
- preventDefault: function() {
- this.isDefaultPrevented = returnTrue;
-
- var e = this.originalEvent;
- if ( !e ) {
- return;
- }
-
- // if preventDefault exists run it on the original event
- if ( e.preventDefault ) {
- e.preventDefault();
-
- // otherwise set the returnValue property of the original event to false (IE)
- } else {
- e.returnValue = false;
- }
- },
- stopPropagation: function() {
- this.isPropagationStopped = returnTrue;
-
- var e = this.originalEvent;
- if ( !e ) {
- return;
- }
- // if stopPropagation exists run it on the original event
- if ( e.stopPropagation ) {
- e.stopPropagation();
- }
- // otherwise set the cancelBubble property of the original event to true (IE)
- e.cancelBubble = true;
- },
- stopImmediatePropagation: function() {
- this.isImmediatePropagationStopped = returnTrue;
- this.stopPropagation();
- },
- isDefaultPrevented: returnFalse,
- isPropagationStopped: returnFalse,
- isImmediatePropagationStopped: returnFalse
-};
-
-// Create mouseenter/leave events using mouseover/out and event-time checks
-jQuery.each({
- mouseenter: "mouseover",
- mouseleave: "mouseout"
-}, function( orig, fix ) {
- jQuery.event.special[ orig ] = {
- delegateType: fix,
- bindType: fix,
-
- handle: function( event ) {
- var target = this,
- related = event.relatedTarget,
- handleObj = event.handleObj,
- selector = handleObj.selector,
- ret;
-
- // For mousenter/leave call the handler if related is outside the target.
- // NB: No relatedTarget if the mouse left/entered the browser window
- if ( !related || (related !== target && !jQuery.contains( target, related )) ) {
- event.type = handleObj.origType;
- ret = handleObj.handler.apply( this, arguments );
- event.type = fix;
- }
- return ret;
- }
- };
-});
-
-// IE submit delegation
-if ( !jQuery.support.submitBubbles ) {
-
- jQuery.event.special.submit = {
- setup: function() {
- // Only need this for delegated form submit events
- if ( jQuery.nodeName( this, "form" ) ) {
- return false;
- }
-
- // Lazy-add a submit handler when a descendant form may potentially be submitted
- jQuery.event.add( this, "click._submit keypress._submit", function( e ) {
- // Node name check avoids a VML-related crash in IE (#9807)
- var elem = e.target,
- form = jQuery.nodeName( elem, "input" ) || jQuery.nodeName( elem, "button" ) ? elem.form : undefined;
- if ( form && !form._submit_attached ) {
- jQuery.event.add( form, "submit._submit", function( event ) {
- event._submit_bubble = true;
- });
- form._submit_attached = true;
- }
- });
- // return undefined since we don't need an event listener
- },
-
- postDispatch: function( event ) {
- // If form was submitted by the user, bubble the event up the tree
- if ( event._submit_bubble ) {
- delete event._submit_bubble;
- if ( this.parentNode && !event.isTrigger ) {
- jQuery.event.simulate( "submit", this.parentNode, event, true );
- }
- }
- },
-
- teardown: function() {
- // Only need this for delegated form submit events
- if ( jQuery.nodeName( this, "form" ) ) {
- return false;
- }
-
- // Remove delegated handlers; cleanData eventually reaps submit handlers attached above
- jQuery.event.remove( this, "._submit" );
- }
- };
-}
-
-// IE change delegation and checkbox/radio fix
-if ( !jQuery.support.changeBubbles ) {
-
- jQuery.event.special.change = {
-
- setup: function() {
-
- if ( rformElems.test( this.nodeName ) ) {
- // IE doesn't fire change on a check/radio until blur; trigger it on click
- // after a propertychange. Eat the blur-change in special.change.handle.
- // This still fires onchange a second time for check/radio after blur.
- if ( this.type === "checkbox" || this.type === "radio" ) {
- jQuery.event.add( this, "propertychange._change", function( event ) {
- if ( event.originalEvent.propertyName === "checked" ) {
- this._just_changed = true;
- }
- });
- jQuery.event.add( this, "click._change", function( event ) {
- if ( this._just_changed && !event.isTrigger ) {
- this._just_changed = false;
- jQuery.event.simulate( "change", this, event, true );
- }
- });
- }
- return false;
- }
- // Delegated event; lazy-add a change handler on descendant inputs
- jQuery.event.add( this, "beforeactivate._change", function( e ) {
- var elem = e.target;
-
- if ( rformElems.test( elem.nodeName ) && !elem._change_attached ) {
- jQuery.event.add( elem, "change._change", function( event ) {
- if ( this.parentNode && !event.isSimulated && !event.isTrigger ) {
- jQuery.event.simulate( "change", this.parentNode, event, true );
- }
- });
- elem._change_attached = true;
- }
- });
- },
-
- handle: function( event ) {
- var elem = event.target;
-
- // Swallow native change events from checkbox/radio, we already triggered them above
- if ( this !== elem || event.isSimulated || event.isTrigger || (elem.type !== "radio" && elem.type !== "checkbox") ) {
- return event.handleObj.handler.apply( this, arguments );
- }
- },
-
- teardown: function() {
- jQuery.event.remove( this, "._change" );
-
- return rformElems.test( this.nodeName );
- }
- };
-}
-
-// Create "bubbling" focus and blur events
-if ( !jQuery.support.focusinBubbles ) {
- jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) {
-
- // Attach a single capturing handler while someone wants focusin/focusout
- var attaches = 0,
- handler = function( event ) {
- jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ), true );
- };
-
- jQuery.event.special[ fix ] = {
- setup: function() {
- if ( attaches++ === 0 ) {
- document.addEventListener( orig, handler, true );
- }
- },
- teardown: function() {
- if ( --attaches === 0 ) {
- document.removeEventListener( orig, handler, true );
- }
- }
- };
- });
-}
-
-jQuery.fn.extend({
-
- on: function( types, selector, data, fn, /*INTERNAL*/ one ) {
- var origFn, type;
-
- // Types can be a map of types/handlers
- if ( typeof types === "object" ) {
- // ( types-Object, selector, data )
- if ( typeof selector !== "string" ) { // && selector != null
- // ( types-Object, data )
- data = data || selector;
- selector = undefined;
- }
- for ( type in types ) {
- this.on( type, selector, data, types[ type ], one );
- }
- return this;
- }
-
- if ( data == null && fn == null ) {
- // ( types, fn )
- fn = selector;
- data = selector = undefined;
- } else if ( fn == null ) {
- if ( typeof selector === "string" ) {
- // ( types, selector, fn )
- fn = data;
- data = undefined;
- } else {
- // ( types, data, fn )
- fn = data;
- data = selector;
- selector = undefined;
- }
- }
- if ( fn === false ) {
- fn = returnFalse;
- } else if ( !fn ) {
- return this;
- }
-
- if ( one === 1 ) {
- origFn = fn;
- fn = function( event ) {
- // Can use an empty set, since event contains the info
- jQuery().off( event );
- return origFn.apply( this, arguments );
- };
- // Use same guid so caller can remove using origFn
- fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ );
- }
- return this.each( function() {
- jQuery.event.add( this, types, fn, data, selector );
- });
- },
- one: function( types, selector, data, fn ) {
- return this.on( types, selector, data, fn, 1 );
- },
- off: function( types, selector, fn ) {
- if ( types && types.preventDefault && types.handleObj ) {
- // ( event ) dispatched jQuery.Event
- var handleObj = types.handleObj;
- jQuery( types.delegateTarget ).off(
- handleObj.namespace ? handleObj.origType + "." + handleObj.namespace : handleObj.origType,
- handleObj.selector,
- handleObj.handler
- );
- return this;
- }
- if ( typeof types === "object" ) {
- // ( types-object [, selector] )
- for ( var type in types ) {
- this.off( type, selector, types[ type ] );
- }
- return this;
- }
- if ( selector === false || typeof selector === "function" ) {
- // ( types [, fn] )
- fn = selector;
- selector = undefined;
- }
- if ( fn === false ) {
- fn = returnFalse;
- }
- return this.each(function() {
- jQuery.event.remove( this, types, fn, selector );
- });
- },
-
- bind: function( types, data, fn ) {
- return this.on( types, null, data, fn );
- },
- unbind: function( types, fn ) {
- return this.off( types, null, fn );
- },
-
- live: function( types, data, fn ) {
- jQuery( this.context ).on( types, this.selector, data, fn );
- return this;
- },
- die: function( types, fn ) {
- jQuery( this.context ).off( types, this.selector || "**", fn );
- return this;
- },
-
- delegate: function( selector, types, data, fn ) {
- return this.on( types, selector, data, fn );
- },
- undelegate: function( selector, types, fn ) {
- // ( namespace ) or ( selector, types [, fn] )
- return arguments.length == 1? this.off( selector, "**" ) : this.off( types, selector, fn );
- },
-
- trigger: function( type, data ) {
- return this.each(function() {
- jQuery.event.trigger( type, data, this );
- });
- },
- triggerHandler: function( type, data ) {
- if ( this[0] ) {
- return jQuery.event.trigger( type, data, this[0], true );
- }
- },
-
- toggle: function( fn ) {
- // Save reference to arguments for access in closure
- var args = arguments,
- guid = fn.guid || jQuery.guid++,
- i = 0,
- toggler = function( event ) {
- // Figure out which function to execute
- var lastToggle = ( jQuery._data( this, "lastToggle" + fn.guid ) || 0 ) % i;
- jQuery._data( this, "lastToggle" + fn.guid, lastToggle + 1 );
-
- // Make sure that clicks stop
- event.preventDefault();
-
- // and execute the function
- return args[ lastToggle ].apply( this, arguments ) || false;
- };
-
- // link all the functions, so any of them can unbind this click handler
- toggler.guid = guid;
- while ( i < args.length ) {
- args[ i++ ].guid = guid;
- }
-
- return this.click( toggler );
- },
-
- hover: function( fnOver, fnOut ) {
- return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );
- }
-});
-
-jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblclick " +
- "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " +
- "change select submit keydown keypress keyup error contextmenu").split(" "), function( i, name ) {
-
- // Handle event binding
- jQuery.fn[ name ] = function( data, fn ) {
- if ( fn == null ) {
- fn = data;
- data = null;
- }
-
- return arguments.length > 0 ?
- this.on( name, null, data, fn ) :
- this.trigger( name );
- };
-
- if ( jQuery.attrFn ) {
- jQuery.attrFn[ name ] = true;
- }
-
- if ( rkeyEvent.test( name ) ) {
- jQuery.event.fixHooks[ name ] = jQuery.event.keyHooks;
- }
-
- if ( rmouseEvent.test( name ) ) {
- jQuery.event.fixHooks[ name ] = jQuery.event.mouseHooks;
- }
-});
-
-
-
-/*!
- * Sizzle CSS Selector Engine
- * Copyright 2011, The Dojo Foundation
- * Released under the MIT, BSD, and GPL Licenses.
- * More information: http://sizzlejs.com/
- */
-(function(){
-
-var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,
- expando = "sizcache" + (Math.random() + '').replace('.', ''),
- done = 0,
- toString = Object.prototype.toString,
- hasDuplicate = false,
- baseHasDuplicate = true,
- rBackslash = /\\/g,
- rReturn = /\r\n/g,
- rNonWord = /\W/;
-
-// Here we check if the JavaScript engine is using some sort of
-// optimization where it does not always call our comparision
-// function. If that is the case, discard the hasDuplicate value.
-// Thus far that includes Google Chrome.
-[0, 0].sort(function() {
- baseHasDuplicate = false;
- return 0;
-});
-
-var Sizzle = function( selector, context, results, seed ) {
- results = results || [];
- context = context || document;
-
- var origContext = context;
-
- if ( context.nodeType !== 1 && context.nodeType !== 9 ) {
- return [];
- }
-
- if ( !selector || typeof selector !== "string" ) {
- return results;
- }
-
- var m, set, checkSet, extra, ret, cur, pop, i,
- prune = true,
- contextXML = Sizzle.isXML( context ),
- parts = [],
- soFar = selector;
-
- // Reset the position of the chunker regexp (start from head)
- do {
- chunker.exec( "" );
- m = chunker.exec( soFar );
-
- if ( m ) {
- soFar = m[3];
-
- parts.push( m[1] );
-
- if ( m[2] ) {
- extra = m[3];
- break;
- }
- }
- } while ( m );
-
- if ( parts.length > 1 && origPOS.exec( selector ) ) {
-
- if ( parts.length === 2 && Expr.relative[ parts[0] ] ) {
- set = posProcess( parts[0] + parts[1], context, seed );
-
- } else {
- set = Expr.relative[ parts[0] ] ?
- [ context ] :
- Sizzle( parts.shift(), context );
-
- while ( parts.length ) {
- selector = parts.shift();
-
- if ( Expr.relative[ selector ] ) {
- selector += parts.shift();
- }
-
- set = posProcess( selector, set, seed );
- }
- }
-
- } else {
- // Take a shortcut and set the context if the root selector is an ID
- // (but not if it'll be faster if the inner selector is an ID)
- if ( !seed && parts.length > 1 && context.nodeType === 9 && !contextXML &&
- Expr.match.ID.test(parts[0]) && !Expr.match.ID.test(parts[parts.length - 1]) ) {
-
- ret = Sizzle.find( parts.shift(), context, contextXML );
- context = ret.expr ?
- Sizzle.filter( ret.expr, ret.set )[0] :
- ret.set[0];
- }
-
- if ( context ) {
- ret = seed ?
- { expr: parts.pop(), set: makeArray(seed) } :
- Sizzle.find( parts.pop(), parts.length === 1 && (parts[0] === "~" || parts[0] === "+") && context.parentNode ? context.parentNode : context, contextXML );
-
- set = ret.expr ?
- Sizzle.filter( ret.expr, ret.set ) :
- ret.set;
-
- if ( parts.length > 0 ) {
- checkSet = makeArray( set );
-
- } else {
- prune = false;
- }
-
- while ( parts.length ) {
- cur = parts.pop();
- pop = cur;
-
- if ( !Expr.relative[ cur ] ) {
- cur = "";
- } else {
- pop = parts.pop();
- }
-
- if ( pop == null ) {
- pop = context;
- }
-
- Expr.relative[ cur ]( checkSet, pop, contextXML );
- }
-
- } else {
- checkSet = parts = [];
- }
- }
-
- if ( !checkSet ) {
- checkSet = set;
- }
-
- if ( !checkSet ) {
- Sizzle.error( cur || selector );
- }
-
- if ( toString.call(checkSet) === "[object Array]" ) {
- if ( !prune ) {
- results.push.apply( results, checkSet );
-
- } else if ( context && context.nodeType === 1 ) {
- for ( i = 0; checkSet[i] != null; i++ ) {
- if ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && Sizzle.contains(context, checkSet[i])) ) {
- results.push( set[i] );
- }
- }
-
- } else {
- for ( i = 0; checkSet[i] != null; i++ ) {
- if ( checkSet[i] && checkSet[i].nodeType === 1 ) {
- results.push( set[i] );
- }
- }
- }
-
- } else {
- makeArray( checkSet, results );
- }
-
- if ( extra ) {
- Sizzle( extra, origContext, results, seed );
- Sizzle.uniqueSort( results );
- }
-
- return results;
-};
-
-Sizzle.uniqueSort = function( results ) {
- if ( sortOrder ) {
- hasDuplicate = baseHasDuplicate;
- results.sort( sortOrder );
-
- if ( hasDuplicate ) {
- for ( var i = 1; i < results.length; i++ ) {
- if ( results[i] === results[ i - 1 ] ) {
- results.splice( i--, 1 );
- }
- }
- }
- }
-
- return results;
-};
-
-Sizzle.matches = function( expr, set ) {
- return Sizzle( expr, null, null, set );
-};
-
-Sizzle.matchesSelector = function( node, expr ) {
- return Sizzle( expr, null, null, [node] ).length > 0;
-};
-
-Sizzle.find = function( expr, context, isXML ) {
- var set, i, len, match, type, left;
-
- if ( !expr ) {
- return [];
- }
-
- for ( i = 0, len = Expr.order.length; i < len; i++ ) {
- type = Expr.order[i];
-
- if ( (match = Expr.leftMatch[ type ].exec( expr )) ) {
- left = match[1];
- match.splice( 1, 1 );
-
- if ( left.substr( left.length - 1 ) !== "\\" ) {
- match[1] = (match[1] || "").replace( rBackslash, "" );
- set = Expr.find[ type ]( match, context, isXML );
-
- if ( set != null ) {
- expr = expr.replace( Expr.match[ type ], "" );
- break;
- }
- }
- }
- }
-
- if ( !set ) {
- set = typeof context.getElementsByTagName !== "undefined" ?
- context.getElementsByTagName( "*" ) :
- [];
- }
-
- return { set: set, expr: expr };
-};
-
-Sizzle.filter = function( expr, set, inplace, not ) {
- var match, anyFound,
- type, found, item, filter, left,
- i, pass,
- old = expr,
- result = [],
- curLoop = set,
- isXMLFilter = set && set[0] && Sizzle.isXML( set[0] );
-
- while ( expr && set.length ) {
- for ( type in Expr.filter ) {
- if ( (match = Expr.leftMatch[ type ].exec( expr )) != null && match[2] ) {
- filter = Expr.filter[ type ];
- left = match[1];
-
- anyFound = false;
-
- match.splice(1,1);
-
- if ( left.substr( left.length - 1 ) === "\\" ) {
- continue;
- }
-
- if ( curLoop === result ) {
- result = [];
- }
-
- if ( Expr.preFilter[ type ] ) {
- match = Expr.preFilter[ type ]( match, curLoop, inplace, result, not, isXMLFilter );
-
- if ( !match ) {
- anyFound = found = true;
-
- } else if ( match === true ) {
- continue;
- }
- }
-
- if ( match ) {
- for ( i = 0; (item = curLoop[i]) != null; i++ ) {
- if ( item ) {
- found = filter( item, match, i, curLoop );
- pass = not ^ found;
-
- if ( inplace && found != null ) {
- if ( pass ) {
- anyFound = true;
-
- } else {
- curLoop[i] = false;
- }
-
- } else if ( pass ) {
- result.push( item );
- anyFound = true;
- }
- }
- }
- }
-
- if ( found !== undefined ) {
- if ( !inplace ) {
- curLoop = result;
- }
-
- expr = expr.replace( Expr.match[ type ], "" );
-
- if ( !anyFound ) {
- return [];
- }
-
- break;
- }
- }
- }
-
- // Improper expression
- if ( expr === old ) {
- if ( anyFound == null ) {
- Sizzle.error( expr );
-
- } else {
- break;
- }
- }
-
- old = expr;
- }
-
- return curLoop;
-};
-
-Sizzle.error = function( msg ) {
- throw new Error( "Syntax error, unrecognized expression: " + msg );
-};
-
-/**
- * Utility function for retreiving the text value of an array of DOM nodes
- * @param {Array|Element} elem
- */
-var getText = Sizzle.getText = function( elem ) {
- var i, node,
- nodeType = elem.nodeType,
- ret = "";
-
- if ( nodeType ) {
- if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) {
- // Use textContent || innerText for elements
- if ( typeof elem.textContent === 'string' ) {
- return elem.textContent;
- } else if ( typeof elem.innerText === 'string' ) {
- // Replace IE's carriage returns
- return elem.innerText.replace( rReturn, '' );
- } else {
- // Traverse it's children
- for ( elem = elem.firstChild; elem; elem = elem.nextSibling) {
- ret += getText( elem );
- }
- }
- } else if ( nodeType === 3 || nodeType === 4 ) {
- return elem.nodeValue;
- }
- } else {
-
- // If no nodeType, this is expected to be an array
- for ( i = 0; (node = elem[i]); i++ ) {
- // Do not traverse comment nodes
- if ( node.nodeType !== 8 ) {
- ret += getText( node );
- }
- }
- }
- return ret;
-};
-
-var Expr = Sizzle.selectors = {
- order: [ "ID", "NAME", "TAG" ],
-
- match: {
- ID: /#((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,
- CLASS: /\.((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,
- NAME: /\[name=['"]*((?:[\w\u00c0-\uFFFF\-]|\\.)+)['"]*\]/,
- ATTR: /\[\s*((?:[\w\u00c0-\uFFFF\-]|\\.)+)\s*(?:(\S?=)\s*(?:(['"])(.*?)\3|(#?(?:[\w\u00c0-\uFFFF\-]|\\.)*)|)|)\s*\]/,
- TAG: /^((?:[\w\u00c0-\uFFFF\*\-]|\\.)+)/,
- CHILD: /:(only|nth|last|first)-child(?:\(\s*(even|odd|(?:[+\-]?\d+|(?:[+\-]?\d*)?n\s*(?:[+\-]\s*\d+)?))\s*\))?/,
- POS: /:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^\-]|$)/,
- PSEUDO: /:((?:[\w\u00c0-\uFFFF\-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/
- },
-
- leftMatch: {},
-
- attrMap: {
- "class": "className",
- "for": "htmlFor"
- },
-
- attrHandle: {
- href: function( elem ) {
- return elem.getAttribute( "href" );
- },
- type: function( elem ) {
- return elem.getAttribute( "type" );
- }
- },
-
- relative: {
- "+": function(checkSet, part){
- var isPartStr = typeof part === "string",
- isTag = isPartStr && !rNonWord.test( part ),
- isPartStrNotTag = isPartStr && !isTag;
-
- if ( isTag ) {
- part = part.toLowerCase();
- }
-
- for ( var i = 0, l = checkSet.length, elem; i < l; i++ ) {
- if ( (elem = checkSet[i]) ) {
- while ( (elem = elem.previousSibling) && elem.nodeType !== 1 ) {}
-
- checkSet[i] = isPartStrNotTag || elem && elem.nodeName.toLowerCase() === part ?
- elem || false :
- elem === part;
- }
- }
-
- if ( isPartStrNotTag ) {
- Sizzle.filter( part, checkSet, true );
- }
- },
-
- ">": function( checkSet, part ) {
- var elem,
- isPartStr = typeof part === "string",
- i = 0,
- l = checkSet.length;
-
- if ( isPartStr && !rNonWord.test( part ) ) {
- part = part.toLowerCase();
-
- for ( ; i < l; i++ ) {
- elem = checkSet[i];
-
- if ( elem ) {
- var parent = elem.parentNode;
- checkSet[i] = parent.nodeName.toLowerCase() === part ? parent : false;
- }
- }
-
- } else {
- for ( ; i < l; i++ ) {
- elem = checkSet[i];
-
- if ( elem ) {
- checkSet[i] = isPartStr ?
- elem.parentNode :
- elem.parentNode === part;
- }
- }
-
- if ( isPartStr ) {
- Sizzle.filter( part, checkSet, true );
- }
- }
- },
-
- "": function(checkSet, part, isXML){
- var nodeCheck,
- doneName = done++,
- checkFn = dirCheck;
-
- if ( typeof part === "string" && !rNonWord.test( part ) ) {
- part = part.toLowerCase();
- nodeCheck = part;
- checkFn = dirNodeCheck;
- }
-
- checkFn( "parentNode", part, doneName, checkSet, nodeCheck, isXML );
- },
-
- "~": function( checkSet, part, isXML ) {
- var nodeCheck,
- doneName = done++,
- checkFn = dirCheck;
-
- if ( typeof part === "string" && !rNonWord.test( part ) ) {
- part = part.toLowerCase();
- nodeCheck = part;
- checkFn = dirNodeCheck;
- }
-
- checkFn( "previousSibling", part, doneName, checkSet, nodeCheck, isXML );
- }
- },
-
- find: {
- ID: function( match, context, isXML ) {
- if ( typeof context.getElementById !== "undefined" && !isXML ) {
- var m = context.getElementById(match[1]);
- // Check parentNode to catch when Blackberry 4.6 returns
- // nodes that are no longer in the document #6963
- return m && m.parentNode ? [m] : [];
- }
- },
-
- NAME: function( match, context ) {
- if ( typeof context.getElementsByName !== "undefined" ) {
- var ret = [],
- results = context.getElementsByName( match[1] );
-
- for ( var i = 0, l = results.length; i < l; i++ ) {
- if ( results[i].getAttribute("name") === match[1] ) {
- ret.push( results[i] );
- }
- }
-
- return ret.length === 0 ? null : ret;
- }
- },
-
- TAG: function( match, context ) {
- if ( typeof context.getElementsByTagName !== "undefined" ) {
- return context.getElementsByTagName( match[1] );
- }
- }
- },
- preFilter: {
- CLASS: function( match, curLoop, inplace, result, not, isXML ) {
- match = " " + match[1].replace( rBackslash, "" ) + " ";
-
- if ( isXML ) {
- return match;
- }
-
- for ( var i = 0, elem; (elem = curLoop[i]) != null; i++ ) {
- if ( elem ) {
- if ( not ^ (elem.className && (" " + elem.className + " ").replace(/[\t\n\r]/g, " ").indexOf(match) >= 0) ) {
- if ( !inplace ) {
- result.push( elem );
- }
-
- } else if ( inplace ) {
- curLoop[i] = false;
- }
- }
- }
-
- return false;
- },
-
- ID: function( match ) {
- return match[1].replace( rBackslash, "" );
- },
-
- TAG: function( match, curLoop ) {
- return match[1].replace( rBackslash, "" ).toLowerCase();
- },
-
- CHILD: function( match ) {
- if ( match[1] === "nth" ) {
- if ( !match[2] ) {
- Sizzle.error( match[0] );
- }
-
- match[2] = match[2].replace(/^\+|\s*/g, '');
-
- // parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6'
- var test = /(-?)(\d*)(?:n([+\-]?\d*))?/.exec(
- match[2] === "even" && "2n" || match[2] === "odd" && "2n+1" ||
- !/\D/.test( match[2] ) && "0n+" + match[2] || match[2]);
-
- // calculate the numbers (first)n+(last) including if they are negative
- match[2] = (test[1] + (test[2] || 1)) - 0;
- match[3] = test[3] - 0;
- }
- else if ( match[2] ) {
- Sizzle.error( match[0] );
- }
-
- // TODO: Move to normal caching system
- match[0] = done++;
-
- return match;
- },
-
- ATTR: function( match, curLoop, inplace, result, not, isXML ) {
- var name = match[1] = match[1].replace( rBackslash, "" );
-
- if ( !isXML && Expr.attrMap[name] ) {
- match[1] = Expr.attrMap[name];
- }
-
- // Handle if an un-quoted value was used
- match[4] = ( match[4] || match[5] || "" ).replace( rBackslash, "" );
-
- if ( match[2] === "~=" ) {
- match[4] = " " + match[4] + " ";
- }
-
- return match;
- },
-
- PSEUDO: function( match, curLoop, inplace, result, not ) {
- if ( match[1] === "not" ) {
- // If we're dealing with a complex expression, or a simple one
- if ( ( chunker.exec(match[3]) || "" ).length > 1 || /^\w/.test(match[3]) ) {
- match[3] = Sizzle(match[3], null, null, curLoop);
-
- } else {
- var ret = Sizzle.filter(match[3], curLoop, inplace, true ^ not);
-
- if ( !inplace ) {
- result.push.apply( result, ret );
- }
-
- return false;
- }
-
- } else if ( Expr.match.POS.test( match[0] ) || Expr.match.CHILD.test( match[0] ) ) {
- return true;
- }
-
- return match;
- },
-
- POS: function( match ) {
- match.unshift( true );
-
- return match;
- }
- },
-
- filters: {
- enabled: function( elem ) {
- return elem.disabled === false && elem.type !== "hidden";
- },
-
- disabled: function( elem ) {
- return elem.disabled === true;
- },
-
- checked: function( elem ) {
- return elem.checked === true;
- },
-
- selected: function( elem ) {
- // Accessing this property makes selected-by-default
- // options in Safari work properly
- if ( elem.parentNode ) {
- elem.parentNode.selectedIndex;
- }
-
- return elem.selected === true;
- },
-
- parent: function( elem ) {
- return !!elem.firstChild;
- },
-
- empty: function( elem ) {
- return !elem.firstChild;
- },
-
- has: function( elem, i, match ) {
- return !!Sizzle( match[3], elem ).length;
- },
-
- header: function( elem ) {
- return (/h\d/i).test( elem.nodeName );
- },
-
- text: function( elem ) {
- var attr = elem.getAttribute( "type" ), type = elem.type;
- // IE6 and 7 will map elem.type to 'text' for new HTML5 types (search, etc)
- // use getAttribute instead to test this case
- return elem.nodeName.toLowerCase() === "input" && "text" === type && ( attr === type || attr === null );
- },
-
- radio: function( elem ) {
- return elem.nodeName.toLowerCase() === "input" && "radio" === elem.type;
- },
-
- checkbox: function( elem ) {
- return elem.nodeName.toLowerCase() === "input" && "checkbox" === elem.type;
- },
-
- file: function( elem ) {
- return elem.nodeName.toLowerCase() === "input" && "file" === elem.type;
- },
-
- password: function( elem ) {
- return elem.nodeName.toLowerCase() === "input" && "password" === elem.type;
- },
-
- submit: function( elem ) {
- var name = elem.nodeName.toLowerCase();
- return (name === "input" || name === "button") && "submit" === elem.type;
- },
-
- image: function( elem ) {
- return elem.nodeName.toLowerCase() === "input" && "image" === elem.type;
- },
-
- reset: function( elem ) {
- var name = elem.nodeName.toLowerCase();
- return (name === "input" || name === "button") && "reset" === elem.type;
- },
-
- button: function( elem ) {
- var name = elem.nodeName.toLowerCase();
- return name === "input" && "button" === elem.type || name === "button";
- },
-
- input: function( elem ) {
- return (/input|select|textarea|button/i).test( elem.nodeName );
- },
-
- focus: function( elem ) {
- return elem === elem.ownerDocument.activeElement;
- }
- },
- setFilters: {
- first: function( elem, i ) {
- return i === 0;
- },
-
- last: function( elem, i, match, array ) {
- return i === array.length - 1;
- },
-
- even: function( elem, i ) {
- return i % 2 === 0;
- },
-
- odd: function( elem, i ) {
- return i % 2 === 1;
- },
-
- lt: function( elem, i, match ) {
- return i < match[3] - 0;
- },
-
- gt: function( elem, i, match ) {
- return i > match[3] - 0;
- },
-
- nth: function( elem, i, match ) {
- return match[3] - 0 === i;
- },
-
- eq: function( elem, i, match ) {
- return match[3] - 0 === i;
- }
- },
- filter: {
- PSEUDO: function( elem, match, i, array ) {
- var name = match[1],
- filter = Expr.filters[ name ];
-
- if ( filter ) {
- return filter( elem, i, match, array );
-
- } else if ( name === "contains" ) {
- return (elem.textContent || elem.innerText || getText([ elem ]) || "").indexOf(match[3]) >= 0;
-
- } else if ( name === "not" ) {
- var not = match[3];
-
- for ( var j = 0, l = not.length; j < l; j++ ) {
- if ( not[j] === elem ) {
- return false;
- }
- }
-
- return true;
-
- } else {
- Sizzle.error( name );
- }
- },
-
- CHILD: function( elem, match ) {
- var first, last,
- doneName, parent, cache,
- count, diff,
- type = match[1],
- node = elem;
-
- switch ( type ) {
- case "only":
- case "first":
- while ( (node = node.previousSibling) ) {
- if ( node.nodeType === 1 ) {
- return false;
- }
- }
-
- if ( type === "first" ) {
- return true;
- }
-
- node = elem;
-
- /* falls through */
- case "last":
- while ( (node = node.nextSibling) ) {
- if ( node.nodeType === 1 ) {
- return false;
- }
- }
-
- return true;
-
- case "nth":
- first = match[2];
- last = match[3];
-
- if ( first === 1 && last === 0 ) {
- return true;
- }
-
- doneName = match[0];
- parent = elem.parentNode;
-
- if ( parent && (parent[ expando ] !== doneName || !elem.nodeIndex) ) {
- count = 0;
-
- for ( node = parent.firstChild; node; node = node.nextSibling ) {
- if ( node.nodeType === 1 ) {
- node.nodeIndex = ++count;
- }
- }
-
- parent[ expando ] = doneName;
- }
-
- diff = elem.nodeIndex - last;
-
- if ( first === 0 ) {
- return diff === 0;
-
- } else {
- return ( diff % first === 0 && diff / first >= 0 );
- }
- }
- },
-
- ID: function( elem, match ) {
- return elem.nodeType === 1 && elem.getAttribute("id") === match;
- },
-
- TAG: function( elem, match ) {
- return (match === "*" && elem.nodeType === 1) || !!elem.nodeName && elem.nodeName.toLowerCase() === match;
- },
-
- CLASS: function( elem, match ) {
- return (" " + (elem.className || elem.getAttribute("class")) + " ")
- .indexOf( match ) > -1;
- },
-
- ATTR: function( elem, match ) {
- var name = match[1],
- result = Sizzle.attr ?
- Sizzle.attr( elem, name ) :
- Expr.attrHandle[ name ] ?
- Expr.attrHandle[ name ]( elem ) :
- elem[ name ] != null ?
- elem[ name ] :
- elem.getAttribute( name ),
- value = result + "",
- type = match[2],
- check = match[4];
-
- return result == null ?
- type === "!=" :
- !type && Sizzle.attr ?
- result != null :
- type === "=" ?
- value === check :
- type === "*=" ?
- value.indexOf(check) >= 0 :
- type === "~=" ?
- (" " + value + " ").indexOf(check) >= 0 :
- !check ?
- value && result !== false :
- type === "!=" ?
- value !== check :
- type === "^=" ?
- value.indexOf(check) === 0 :
- type === "$=" ?
- value.substr(value.length - check.length) === check :
- type === "|=" ?
- value === check || value.substr(0, check.length + 1) === check + "-" :
- false;
- },
-
- POS: function( elem, match, i, array ) {
- var name = match[2],
- filter = Expr.setFilters[ name ];
-
- if ( filter ) {
- return filter( elem, i, match, array );
- }
- }
- }
-};
-
-var origPOS = Expr.match.POS,
- fescape = function(all, num){
- return "\\" + (num - 0 + 1);
- };
-
-for ( var type in Expr.match ) {
- Expr.match[ type ] = new RegExp( Expr.match[ type ].source + (/(?![^\[]*\])(?![^\(]*\))/.source) );
- Expr.leftMatch[ type ] = new RegExp( /(^(?:.|\r|\n)*?)/.source + Expr.match[ type ].source.replace(/\\(\d+)/g, fescape) );
-}
-// Expose origPOS
-// "global" as in regardless of relation to brackets/parens
-Expr.match.globalPOS = origPOS;
-
-var makeArray = function( array, results ) {
- array = Array.prototype.slice.call( array, 0 );
-
- if ( results ) {
- results.push.apply( results, array );
- return results;
- }
-
- return array;
-};
-
-// Perform a simple check to determine if the browser is capable of
-// converting a NodeList to an array using builtin methods.
-// Also verifies that the returned array holds DOM nodes
-// (which is not the case in the Blackberry browser)
-try {
- Array.prototype.slice.call( document.documentElement.childNodes, 0 )[0].nodeType;
-
-// Provide a fallback method if it does not work
-} catch( e ) {
- makeArray = function( array, results ) {
- var i = 0,
- ret = results || [];
-
- if ( toString.call(array) === "[object Array]" ) {
- Array.prototype.push.apply( ret, array );
-
- } else {
- if ( typeof array.length === "number" ) {
- for ( var l = array.length; i < l; i++ ) {
- ret.push( array[i] );
- }
-
- } else {
- for ( ; array[i]; i++ ) {
- ret.push( array[i] );
- }
- }
- }
-
- return ret;
- };
-}
-
-var sortOrder, siblingCheck;
-
-if ( document.documentElement.compareDocumentPosition ) {
- sortOrder = function( a, b ) {
- if ( a === b ) {
- hasDuplicate = true;
- return 0;
- }
-
- if ( !a.compareDocumentPosition || !b.compareDocumentPosition ) {
- return a.compareDocumentPosition ? -1 : 1;
- }
-
- return a.compareDocumentPosition(b) & 4 ? -1 : 1;
- };
-
-} else {
- sortOrder = function( a, b ) {
- // The nodes are identical, we can exit early
- if ( a === b ) {
- hasDuplicate = true;
- return 0;
-
- // Fallback to using sourceIndex (in IE) if it's available on both nodes
- } else if ( a.sourceIndex && b.sourceIndex ) {
- return a.sourceIndex - b.sourceIndex;
- }
-
- var al, bl,
- ap = [],
- bp = [],
- aup = a.parentNode,
- bup = b.parentNode,
- cur = aup;
-
- // If the nodes are siblings (or identical) we can do a quick check
- if ( aup === bup ) {
- return siblingCheck( a, b );
-
- // If no parents were found then the nodes are disconnected
- } else if ( !aup ) {
- return -1;
-
- } else if ( !bup ) {
- return 1;
- }
-
- // Otherwise they're somewhere else in the tree so we need
- // to build up a full list of the parentNodes for comparison
- while ( cur ) {
- ap.unshift( cur );
- cur = cur.parentNode;
- }
-
- cur = bup;
-
- while ( cur ) {
- bp.unshift( cur );
- cur = cur.parentNode;
- }
-
- al = ap.length;
- bl = bp.length;
-
- // Start walking down the tree looking for a discrepancy
- for ( var i = 0; i < al && i < bl; i++ ) {
- if ( ap[i] !== bp[i] ) {
- return siblingCheck( ap[i], bp[i] );
- }
- }
-
- // We ended someplace up the tree so do a sibling check
- return i === al ?
- siblingCheck( a, bp[i], -1 ) :
- siblingCheck( ap[i], b, 1 );
- };
-
- siblingCheck = function( a, b, ret ) {
- if ( a === b ) {
- return ret;
- }
-
- var cur = a.nextSibling;
-
- while ( cur ) {
- if ( cur === b ) {
- return -1;
- }
-
- cur = cur.nextSibling;
- }
-
- return 1;
- };
-}
-
-// Check to see if the browser returns elements by name when
-// querying by getElementById (and provide a workaround)
-(function(){
- // We're going to inject a fake input element with a specified name
- var form = document.createElement("div"),
- id = "script" + (new Date()).getTime(),
- root = document.documentElement;
-
- form.innerHTML = "";
-
- // Inject it into the root element, check its status, and remove it quickly
- root.insertBefore( form, root.firstChild );
-
- // The workaround has to do additional checks after a getElementById
- // Which slows things down for other browsers (hence the branching)
- if ( document.getElementById( id ) ) {
- Expr.find.ID = function( match, context, isXML ) {
- if ( typeof context.getElementById !== "undefined" && !isXML ) {
- var m = context.getElementById(match[1]);
-
- return m ?
- m.id === match[1] || typeof m.getAttributeNode !== "undefined" && m.getAttributeNode("id").nodeValue === match[1] ?
- [m] :
- undefined :
- [];
- }
- };
-
- Expr.filter.ID = function( elem, match ) {
- var node = typeof elem.getAttributeNode !== "undefined" && elem.getAttributeNode("id");
-
- return elem.nodeType === 1 && node && node.nodeValue === match;
- };
- }
-
- root.removeChild( form );
-
- // release memory in IE
- root = form = null;
-})();
-
-(function(){
- // Check to see if the browser returns only elements
- // when doing getElementsByTagName("*")
-
- // Create a fake element
- var div = document.createElement("div");
- div.appendChild( document.createComment("") );
-
- // Make sure no comments are found
- if ( div.getElementsByTagName("*").length > 0 ) {
- Expr.find.TAG = function( match, context ) {
- var results = context.getElementsByTagName( match[1] );
-
- // Filter out possible comments
- if ( match[1] === "*" ) {
- var tmp = [];
-
- for ( var i = 0; results[i]; i++ ) {
- if ( results[i].nodeType === 1 ) {
- tmp.push( results[i] );
- }
- }
-
- results = tmp;
- }
-
- return results;
- };
- }
-
- // Check to see if an attribute returns normalized href attributes
- div.innerHTML = "";
-
- if ( div.firstChild && typeof div.firstChild.getAttribute !== "undefined" &&
- div.firstChild.getAttribute("href") !== "#" ) {
-
- Expr.attrHandle.href = function( elem ) {
- return elem.getAttribute( "href", 2 );
- };
- }
-
- // release memory in IE
- div = null;
-})();
-
-if ( document.querySelectorAll ) {
- (function(){
- var oldSizzle = Sizzle,
- div = document.createElement("div"),
- id = "__sizzle__";
-
- div.innerHTML = "";
-
- // Safari can't handle uppercase or unicode characters when
- // in quirks mode.
- if ( div.querySelectorAll && div.querySelectorAll(".TEST").length === 0 ) {
- return;
- }
-
- Sizzle = function( query, context, extra, seed ) {
- context = context || document;
-
- // Only use querySelectorAll on non-XML documents
- // (ID selectors don't work in non-HTML documents)
- if ( !seed && !Sizzle.isXML(context) ) {
- // See if we find a selector to speed up
- var match = /^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec( query );
-
- if ( match && (context.nodeType === 1 || context.nodeType === 9) ) {
- // Speed-up: Sizzle("TAG")
- if ( match[1] ) {
- return makeArray( context.getElementsByTagName( query ), extra );
-
- // Speed-up: Sizzle(".CLASS")
- } else if ( match[2] && Expr.find.CLASS && context.getElementsByClassName ) {
- return makeArray( context.getElementsByClassName( match[2] ), extra );
- }
- }
-
- if ( context.nodeType === 9 ) {
- // Speed-up: Sizzle("body")
- // The body element only exists once, optimize finding it
- if ( query === "body" && context.body ) {
- return makeArray( [ context.body ], extra );
-
- // Speed-up: Sizzle("#ID")
- } else if ( match && match[3] ) {
- var elem = context.getElementById( match[3] );
-
- // Check parentNode to catch when Blackberry 4.6 returns
- // nodes that are no longer in the document #6963
- if ( elem && elem.parentNode ) {
- // Handle the case where IE and Opera return items
- // by name instead of ID
- if ( elem.id === match[3] ) {
- return makeArray( [ elem ], extra );
- }
-
- } else {
- return makeArray( [], extra );
- }
- }
-
- try {
- return makeArray( context.querySelectorAll(query), extra );
- } catch(qsaError) {}
-
- // qSA works strangely on Element-rooted queries
- // We can work around this by specifying an extra ID on the root
- // and working up from there (Thanks to Andrew Dupont for the technique)
- // IE 8 doesn't work on object elements
- } else if ( context.nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) {
- var oldContext = context,
- old = context.getAttribute( "id" ),
- nid = old || id,
- hasParent = context.parentNode,
- relativeHierarchySelector = /^\s*[+~]/.test( query );
-
- if ( !old ) {
- context.setAttribute( "id", nid );
- } else {
- nid = nid.replace( /'/g, "\\$&" );
- }
- if ( relativeHierarchySelector && hasParent ) {
- context = context.parentNode;
- }
-
- try {
- if ( !relativeHierarchySelector || hasParent ) {
- return makeArray( context.querySelectorAll( "[id='" + nid + "'] " + query ), extra );
- }
-
- } catch(pseudoError) {
- } finally {
- if ( !old ) {
- oldContext.removeAttribute( "id" );
- }
- }
- }
- }
-
- return oldSizzle(query, context, extra, seed);
- };
-
- for ( var prop in oldSizzle ) {
- Sizzle[ prop ] = oldSizzle[ prop ];
- }
-
- // release memory in IE
- div = null;
- })();
-}
-
-(function(){
- var html = document.documentElement,
- matches = html.matchesSelector || html.mozMatchesSelector || html.webkitMatchesSelector || html.msMatchesSelector;
-
- if ( matches ) {
- // Check to see if it's possible to do matchesSelector
- // on a disconnected node (IE 9 fails this)
- var disconnectedMatch = !matches.call( document.createElement( "div" ), "div" ),
- pseudoWorks = false;
-
- try {
- // This should fail with an exception
- // Gecko does not error, returns false instead
- matches.call( document.documentElement, "[test!='']:sizzle" );
-
- } catch( pseudoError ) {
- pseudoWorks = true;
- }
-
- Sizzle.matchesSelector = function( node, expr ) {
- // Make sure that attribute selectors are quoted
- expr = expr.replace(/\=\s*([^'"\]]*)\s*\]/g, "='$1']");
-
- if ( !Sizzle.isXML( node ) ) {
- try {
- if ( pseudoWorks || !Expr.match.PSEUDO.test( expr ) && !/!=/.test( expr ) ) {
- var ret = matches.call( node, expr );
-
- // IE 9's matchesSelector returns false on disconnected nodes
- if ( ret || !disconnectedMatch ||
- // As well, disconnected nodes are said to be in a document
- // fragment in IE 9, so check for that
- node.document && node.document.nodeType !== 11 ) {
- return ret;
- }
- }
- } catch(e) {}
- }
-
- return Sizzle(expr, null, null, [node]).length > 0;
- };
- }
-})();
-
-(function(){
- var div = document.createElement("div");
-
- div.innerHTML = "";
-
- // Opera can't find a second classname (in 9.6)
- // Also, make sure that getElementsByClassName actually exists
- if ( !div.getElementsByClassName || div.getElementsByClassName("e").length === 0 ) {
- return;
- }
-
- // Safari caches class attributes, doesn't catch changes (in 3.2)
- div.lastChild.className = "e";
-
- if ( div.getElementsByClassName("e").length === 1 ) {
- return;
- }
-
- Expr.order.splice(1, 0, "CLASS");
- Expr.find.CLASS = function( match, context, isXML ) {
- if ( typeof context.getElementsByClassName !== "undefined" && !isXML ) {
- return context.getElementsByClassName(match[1]);
- }
- };
-
- // release memory in IE
- div = null;
-})();
-
-function dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {
- for ( var i = 0, l = checkSet.length; i < l; i++ ) {
- var elem = checkSet[i];
-
- if ( elem ) {
- var match = false;
-
- elem = elem[dir];
-
- while ( elem ) {
- if ( elem[ expando ] === doneName ) {
- match = checkSet[elem.sizset];
- break;
- }
-
- if ( elem.nodeType === 1 && !isXML ){
- elem[ expando ] = doneName;
- elem.sizset = i;
- }
-
- if ( elem.nodeName.toLowerCase() === cur ) {
- match = elem;
- break;
- }
-
- elem = elem[dir];
- }
-
- checkSet[i] = match;
- }
- }
-}
-
-function dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {
- for ( var i = 0, l = checkSet.length; i < l; i++ ) {
- var elem = checkSet[i];
-
- if ( elem ) {
- var match = false;
-
- elem = elem[dir];
-
- while ( elem ) {
- if ( elem[ expando ] === doneName ) {
- match = checkSet[elem.sizset];
- break;
- }
-
- if ( elem.nodeType === 1 ) {
- if ( !isXML ) {
- elem[ expando ] = doneName;
- elem.sizset = i;
- }
-
- if ( typeof cur !== "string" ) {
- if ( elem === cur ) {
- match = true;
- break;
- }
-
- } else if ( Sizzle.filter( cur, [elem] ).length > 0 ) {
- match = elem;
- break;
- }
- }
-
- elem = elem[dir];
- }
-
- checkSet[i] = match;
- }
- }
-}
-
-if ( document.documentElement.contains ) {
- Sizzle.contains = function( a, b ) {
- return a !== b && (a.contains ? a.contains(b) : true);
- };
-
-} else if ( document.documentElement.compareDocumentPosition ) {
- Sizzle.contains = function( a, b ) {
- return !!(a.compareDocumentPosition(b) & 16);
- };
-
-} else {
- Sizzle.contains = function() {
- return false;
- };
-}
-
-Sizzle.isXML = function( elem ) {
- // documentElement is verified for cases where it doesn't yet exist
- // (such as loading iframes in IE - #4833)
- var documentElement = (elem ? elem.ownerDocument || elem : 0).documentElement;
-
- return documentElement ? documentElement.nodeName !== "HTML" : false;
-};
-
-var posProcess = function( selector, context, seed ) {
- var match,
- tmpSet = [],
- later = "",
- root = context.nodeType ? [context] : context;
-
- // Position selectors must be done after the filter
- // And so must :not(positional) so we move all PSEUDOs to the end
- while ( (match = Expr.match.PSEUDO.exec( selector )) ) {
- later += match[0];
- selector = selector.replace( Expr.match.PSEUDO, "" );
- }
-
- selector = Expr.relative[selector] ? selector + "*" : selector;
-
- for ( var i = 0, l = root.length; i < l; i++ ) {
- Sizzle( selector, root[i], tmpSet, seed );
- }
-
- return Sizzle.filter( later, tmpSet );
-};
-
-// EXPOSE
-// Override sizzle attribute retrieval
-Sizzle.attr = jQuery.attr;
-Sizzle.selectors.attrMap = {};
-jQuery.find = Sizzle;
-jQuery.expr = Sizzle.selectors;
-jQuery.expr[":"] = jQuery.expr.filters;
-jQuery.unique = Sizzle.uniqueSort;
-jQuery.text = Sizzle.getText;
-jQuery.isXMLDoc = Sizzle.isXML;
-jQuery.contains = Sizzle.contains;
-
-
-})();
-
-
-var runtil = /Until$/,
- rparentsprev = /^(?:parents|prevUntil|prevAll)/,
- // Note: This RegExp should be improved, or likely pulled from Sizzle
- rmultiselector = /,/,
- isSimple = /^.[^:#\[\.,]*$/,
- slice = Array.prototype.slice,
- POS = jQuery.expr.match.globalPOS,
- // methods guaranteed to produce a unique set when starting from a unique set
- guaranteedUnique = {
- children: true,
- contents: true,
- next: true,
- prev: true
- };
-
-jQuery.fn.extend({
- find: function( selector ) {
- var self = this,
- i, l;
-
- if ( typeof selector !== "string" ) {
- return jQuery( selector ).filter(function() {
- for ( i = 0, l = self.length; i < l; i++ ) {
- if ( jQuery.contains( self[ i ], this ) ) {
- return true;
- }
- }
- });
- }
-
- var ret = this.pushStack( "", "find", selector ),
- length, n, r;
-
- for ( i = 0, l = this.length; i < l; i++ ) {
- length = ret.length;
- jQuery.find( selector, this[i], ret );
-
- if ( i > 0 ) {
- // Make sure that the results are unique
- for ( n = length; n < ret.length; n++ ) {
- for ( r = 0; r < length; r++ ) {
- if ( ret[r] === ret[n] ) {
- ret.splice(n--, 1);
- break;
- }
- }
- }
- }
- }
-
- return ret;
- },
-
- has: function( target ) {
- var targets = jQuery( target );
- return this.filter(function() {
- for ( var i = 0, l = targets.length; i < l; i++ ) {
- if ( jQuery.contains( this, targets[i] ) ) {
- return true;
- }
- }
- });
- },
-
- not: function( selector ) {
- return this.pushStack( winnow(this, selector, false), "not", selector);
- },
-
- filter: function( selector ) {
- return this.pushStack( winnow(this, selector, true), "filter", selector );
- },
-
- is: function( selector ) {
- return !!selector && (
- typeof selector === "string" ?
- // If this is a positional selector, check membership in the returned set
- // so $("p:first").is("p:last") won't return true for a doc with two "p".
- POS.test( selector ) ?
- jQuery( selector, this.context ).index( this[0] ) >= 0 :
- jQuery.filter( selector, this ).length > 0 :
- this.filter( selector ).length > 0 );
- },
-
- closest: function( selectors, context ) {
- var ret = [], i, l, cur = this[0];
-
- // Array (deprecated as of jQuery 1.7)
- if ( jQuery.isArray( selectors ) ) {
- var level = 1;
-
- while ( cur && cur.ownerDocument && cur !== context ) {
- for ( i = 0; i < selectors.length; i++ ) {
-
- if ( jQuery( cur ).is( selectors[ i ] ) ) {
- ret.push({ selector: selectors[ i ], elem: cur, level: level });
- }
- }
-
- cur = cur.parentNode;
- level++;
- }
-
- return ret;
- }
-
- // String
- var pos = POS.test( selectors ) || typeof selectors !== "string" ?
- jQuery( selectors, context || this.context ) :
- 0;
-
- for ( i = 0, l = this.length; i < l; i++ ) {
- cur = this[i];
-
- while ( cur ) {
- if ( pos ? pos.index(cur) > -1 : jQuery.find.matchesSelector(cur, selectors) ) {
- ret.push( cur );
- break;
-
- } else {
- cur = cur.parentNode;
- if ( !cur || !cur.ownerDocument || cur === context || cur.nodeType === 11 ) {
- break;
- }
- }
- }
- }
-
- ret = ret.length > 1 ? jQuery.unique( ret ) : ret;
-
- return this.pushStack( ret, "closest", selectors );
- },
-
- // Determine the position of an element within
- // the matched set of elements
- index: function( elem ) {
-
- // No argument, return index in parent
- if ( !elem ) {
- return ( this[0] && this[0].parentNode ) ? this.prevAll().length : -1;
- }
-
- // index in selector
- if ( typeof elem === "string" ) {
- return jQuery.inArray( this[0], jQuery( elem ) );
- }
-
- // Locate the position of the desired element
- return jQuery.inArray(
- // If it receives a jQuery object, the first element is used
- elem.jquery ? elem[0] : elem, this );
- },
-
- add: function( selector, context ) {
- var set = typeof selector === "string" ?
- jQuery( selector, context ) :
- jQuery.makeArray( selector && selector.nodeType ? [ selector ] : selector ),
- all = jQuery.merge( this.get(), set );
-
- return this.pushStack( isDisconnected( set[0] ) || isDisconnected( all[0] ) ?
- all :
- jQuery.unique( all ) );
- },
-
- andSelf: function() {
- return this.add( this.prevObject );
- }
-});
-
-// A painfully simple check to see if an element is disconnected
-// from a document (should be improved, where feasible).
-function isDisconnected( node ) {
- return !node || !node.parentNode || node.parentNode.nodeType === 11;
-}
-
-jQuery.each({
- parent: function( elem ) {
- var parent = elem.parentNode;
- return parent && parent.nodeType !== 11 ? parent : null;
- },
- parents: function( elem ) {
- return jQuery.dir( elem, "parentNode" );
- },
- parentsUntil: function( elem, i, until ) {
- return jQuery.dir( elem, "parentNode", until );
- },
- next: function( elem ) {
- return jQuery.nth( elem, 2, "nextSibling" );
- },
- prev: function( elem ) {
- return jQuery.nth( elem, 2, "previousSibling" );
- },
- nextAll: function( elem ) {
- return jQuery.dir( elem, "nextSibling" );
- },
- prevAll: function( elem ) {
- return jQuery.dir( elem, "previousSibling" );
- },
- nextUntil: function( elem, i, until ) {
- return jQuery.dir( elem, "nextSibling", until );
- },
- prevUntil: function( elem, i, until ) {
- return jQuery.dir( elem, "previousSibling", until );
- },
- siblings: function( elem ) {
- return jQuery.sibling( ( elem.parentNode || {} ).firstChild, elem );
- },
- children: function( elem ) {
- return jQuery.sibling( elem.firstChild );
- },
- contents: function( elem ) {
- return jQuery.nodeName( elem, "iframe" ) ?
- elem.contentDocument || elem.contentWindow.document :
- jQuery.makeArray( elem.childNodes );
- }
-}, function( name, fn ) {
- jQuery.fn[ name ] = function( until, selector ) {
- var ret = jQuery.map( this, fn, until );
-
- if ( !runtil.test( name ) ) {
- selector = until;
- }
-
- if ( selector && typeof selector === "string" ) {
- ret = jQuery.filter( selector, ret );
- }
-
- ret = this.length > 1 && !guaranteedUnique[ name ] ? jQuery.unique( ret ) : ret;
-
- if ( (this.length > 1 || rmultiselector.test( selector )) && rparentsprev.test( name ) ) {
- ret = ret.reverse();
- }
-
- return this.pushStack( ret, name, slice.call( arguments ).join(",") );
- };
-});
-
-jQuery.extend({
- filter: function( expr, elems, not ) {
- if ( not ) {
- expr = ":not(" + expr + ")";
- }
-
- return elems.length === 1 ?
- jQuery.find.matchesSelector(elems[0], expr) ? [ elems[0] ] : [] :
- jQuery.find.matches(expr, elems);
- },
-
- dir: function( elem, dir, until ) {
- var matched = [],
- cur = elem[ dir ];
-
- while ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) {
- if ( cur.nodeType === 1 ) {
- matched.push( cur );
- }
- cur = cur[dir];
- }
- return matched;
- },
-
- nth: function( cur, result, dir, elem ) {
- result = result || 1;
- var num = 0;
-
- for ( ; cur; cur = cur[dir] ) {
- if ( cur.nodeType === 1 && ++num === result ) {
- break;
- }
- }
-
- return cur;
- },
-
- sibling: function( n, elem ) {
- var r = [];
-
- for ( ; n; n = n.nextSibling ) {
- if ( n.nodeType === 1 && n !== elem ) {
- r.push( n );
- }
- }
-
- return r;
- }
-});
-
-// Implement the identical functionality for filter and not
-function winnow( elements, qualifier, keep ) {
-
- // Can't pass null or undefined to indexOf in Firefox 4
- // Set to 0 to skip string check
- qualifier = qualifier || 0;
-
- if ( jQuery.isFunction( qualifier ) ) {
- return jQuery.grep(elements, function( elem, i ) {
- var retVal = !!qualifier.call( elem, i, elem );
- return retVal === keep;
- });
-
- } else if ( qualifier.nodeType ) {
- return jQuery.grep(elements, function( elem, i ) {
- return ( elem === qualifier ) === keep;
- });
-
- } else if ( typeof qualifier === "string" ) {
- var filtered = jQuery.grep(elements, function( elem ) {
- return elem.nodeType === 1;
- });
-
- if ( isSimple.test( qualifier ) ) {
- return jQuery.filter(qualifier, filtered, !keep);
- } else {
- qualifier = jQuery.filter( qualifier, filtered );
- }
- }
-
- return jQuery.grep(elements, function( elem, i ) {
- return ( jQuery.inArray( elem, qualifier ) >= 0 ) === keep;
- });
-}
-
-
-
-
-function createSafeFragment( document ) {
- var list = nodeNames.split( "|" ),
- safeFrag = document.createDocumentFragment();
-
- if ( safeFrag.createElement ) {
- while ( list.length ) {
- safeFrag.createElement(
- list.pop()
- );
- }
- }
- return safeFrag;
-}
-
-var nodeNames = "abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|" +
- "header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",
- rinlinejQuery = / jQuery\d+="(?:\d+|null)"/g,
- rleadingWhitespace = /^\s+/,
- rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,
- rtagName = /<([\w:]+)/,
- rtbody = /]", "i"),
- // checked="checked" or checked
- rchecked = /checked\s*(?:[^=]|=\s*.checked.)/i,
- rscriptType = /\/(java|ecma)script/i,
- rcleanScript = /^\s*", "" ],
- legend: [ 1, "" ],
- thead: [ 1, "
-
-
- it('should auto compile', function() {
- expect(element('div[compile]').text()).toBe('Hello Angular');
- input('html').enter('{{name}}!');
- expect(element('div[compile]').text()).toBe('Angular!');
- });
-
-
-
- *
- *
- * @param {string|DOMElement} element Element or HTML string to compile into a template function.
- * @param {function(angular.Scope[, cloneAttachFn]} transclude function available to directives.
- * @param {number} maxPriority only apply directives lower then given priority (Only effects the
- * root element(s), not their children)
- * @returns {function(scope[, cloneAttachFn])} a link function which is used to bind template
- * (a DOM element/tree) to a scope. Where:
- *
- * * `scope` - A {@link ng.$rootScope.Scope Scope} to bind to.
- * * `cloneAttachFn` - If `cloneAttachFn` is provided, then the link function will clone the
- * `template` and call the `cloneAttachFn` function allowing the caller to attach the
- * cloned elements to the DOM document at the appropriate place. The `cloneAttachFn` is
- * called as: `cloneAttachFn(clonedElement, scope)` where:
- *
- * * `clonedElement` - is a clone of the original `element` passed into the compiler.
- * * `scope` - is the current scope with which the linking function is working with.
- *
- * Calling the linking function returns the element of the template. It is either the original element
- * passed in, or the clone of the element if the `cloneAttachFn` is provided.
- *
- * After linking the view is not updated until after a call to $digest which typically is done by
- * Angular automatically.
- *
- * If you need access to the bound view, there are two ways to do it:
- *
- * - If you are not asking the linking function to clone the template, create the DOM element(s)
- * before you send them to the compiler and keep this reference around.
- *
- * var element = $compile('
{{total}}
')(scope);
- *
- *
- * - if on the other hand, you need the element to be cloned, the view reference from the original
- * example would not point to the clone, but rather to the original template that was cloned. In
- * this case, you can access the clone via the cloneAttachFn:
- *
- * var templateHTML = angular.element('
{{total}}
'),
- * scope = ....;
- *
- * var clonedElement = $compile(templateHTML)(scope, function(clonedElement, scope) {
- * //attach the clone to DOM document at the right place
- * });
- *
- * //now we have reference to the cloned DOM via `clone`
- *
- *
- *
- * For information on how the compiler works, see the
- * {@link guide/compiler Angular HTML Compiler} section of the Developer Guide.
- */
-
-
-/**
- * @ngdoc service
- * @name ng.$compileProvider
- * @function
- *
- * @description
- */
-$CompileProvider.$inject = ['$provide'];
-function $CompileProvider($provide) {
- var hasDirectives = {},
- Suffix = 'Directive',
- COMMENT_DIRECTIVE_REGEXP = /^\s*directive\:\s*([\d\w\-_]+)\s+(.*)$/,
- CLASS_DIRECTIVE_REGEXP = /(([\d\w\-_]+)(?:\:([^;]+))?;?)/,
- MULTI_ROOT_TEMPLATE_ERROR = 'Template must have exactly one root element. was: ',
- urlSanitizationWhitelist = /^\s*(https?|ftp|mailto|file):/;
-
-
- /**
- * @ngdoc function
- * @name ng.$compileProvider#directive
- * @methodOf ng.$compileProvider
- * @function
- *
- * @description
- * Register a new directives with the compiler.
- *
- * @param {string} name Name of the directive in camel-case. (ie ngBind which will match as
- * ng-bind).
- * @param {function} directiveFactory An injectable directive factroy function. See {@link guide/directive} for more
- * info.
- * @returns {ng.$compileProvider} Self for chaining.
- */
- this.directive = function registerDirective(name, directiveFactory) {
- if (isString(name)) {
- assertArg(directiveFactory, 'directive');
- if (!hasDirectives.hasOwnProperty(name)) {
- hasDirectives[name] = [];
- $provide.factory(name + Suffix, ['$injector', '$exceptionHandler',
- function($injector, $exceptionHandler) {
- var directives = [];
- forEach(hasDirectives[name], function(directiveFactory) {
- try {
- var directive = $injector.invoke(directiveFactory);
- if (isFunction(directive)) {
- directive = { compile: valueFn(directive) };
- } else if (!directive.compile && directive.link) {
- directive.compile = valueFn(directive.link);
- }
- directive.priority = directive.priority || 0;
- directive.name = directive.name || name;
- directive.require = directive.require || (directive.controller && directive.name);
- directive.restrict = directive.restrict || 'A';
- directives.push(directive);
- } catch (e) {
- $exceptionHandler(e);
- }
- });
- return directives;
- }]);
- }
- hasDirectives[name].push(directiveFactory);
- } else {
- forEach(name, reverseParams(registerDirective));
- }
- return this;
- };
-
-
- /**
- * @ngdoc function
- * @name ng.$compileProvider#urlSanitizationWhitelist
- * @methodOf ng.$compileProvider
- * @function
- *
- * @description
- * Retrieves or overrides the default regular expression that is used for whitelisting of safe
- * urls during a[href] sanitization.
- *
- * The sanitization is a security measure aimed at prevent XSS attacks via html links.
- *
- * Any url about to be assigned to a[href] via data-binding is first normalized and turned into an
- * absolute url. Afterwards the url is matched against the `urlSanitizationWhitelist` regular
- * expression. If a match is found the original url is written into the dom. Otherwise the
- * absolute url is prefixed with `'unsafe:'` string and only then it is written into the DOM.
- *
- * @param {RegExp=} regexp New regexp to whitelist urls with.
- * @returns {RegExp|ng.$compileProvider} Current RegExp if called without value or self for
- * chaining otherwise.
- */
- this.urlSanitizationWhitelist = function(regexp) {
- if (isDefined(regexp)) {
- urlSanitizationWhitelist = regexp;
- return this;
- }
- return urlSanitizationWhitelist;
- };
-
-
- this.$get = [
- '$injector', '$interpolate', '$exceptionHandler', '$http', '$templateCache', '$parse',
- '$controller', '$rootScope', '$document',
- function($injector, $interpolate, $exceptionHandler, $http, $templateCache, $parse,
- $controller, $rootScope, $document) {
-
- var Attributes = function(element, attr) {
- this.$$element = element;
- this.$attr = attr || {};
- };
-
- Attributes.prototype = {
- $normalize: directiveNormalize,
-
-
- /**
- * Set a normalized attribute on the element in a way such that all directives
- * can share the attribute. This function properly handles boolean attributes.
- * @param {string} key Normalized key. (ie ngAttribute)
- * @param {string|boolean} value The value to set. If `null` attribute will be deleted.
- * @param {boolean=} writeAttr If false, does not write the value to DOM element attribute.
- * Defaults to true.
- * @param {string=} attrName Optional none normalized name. Defaults to key.
- */
- $set: function(key, value, writeAttr, attrName) {
- var booleanKey = getBooleanAttrName(this.$$element[0], key),
- $$observers = this.$$observers,
- normalizedVal;
-
- if (booleanKey) {
- this.$$element.prop(key, value);
- attrName = booleanKey;
- }
-
- this[key] = value;
-
- // translate normalized key to actual key
- if (attrName) {
- this.$attr[key] = attrName;
- } else {
- attrName = this.$attr[key];
- if (!attrName) {
- this.$attr[key] = attrName = snake_case(key, '-');
- }
- }
-
-
- // sanitize a[href] values
- if (nodeName_(this.$$element[0]) === 'A' && key === 'href') {
- urlSanitizationNode.setAttribute('href', value);
-
- // href property always returns normalized absolute url, so we can match against that
- normalizedVal = urlSanitizationNode.href;
- if (!normalizedVal.match(urlSanitizationWhitelist)) {
- this[key] = value = 'unsafe:' + normalizedVal;
- }
- }
-
-
- if (writeAttr !== false) {
- if (value === null || value === undefined) {
- this.$$element.removeAttr(attrName);
- } else {
- this.$$element.attr(attrName, value);
- }
- }
-
- // fire observers
- $$observers && forEach($$observers[key], function(fn) {
- try {
- fn(value);
- } catch (e) {
- $exceptionHandler(e);
- }
- });
- },
-
-
- /**
- * Observe an interpolated attribute.
- * The observer will never be called, if given attribute is not interpolated.
- *
- * @param {string} key Normalized key. (ie ngAttribute) .
- * @param {function(*)} fn Function that will be called whenever the attribute value changes.
- * @returns {function(*)} the `fn` Function passed in.
- */
- $observe: function(key, fn) {
- var attrs = this,
- $$observers = (attrs.$$observers || (attrs.$$observers = {})),
- listeners = ($$observers[key] || ($$observers[key] = []));
-
- listeners.push(fn);
- $rootScope.$evalAsync(function() {
- if (!listeners.$$inter) {
- // no one registered attribute interpolation function, so lets call it manually
- fn(attrs[key]);
- }
- });
- return fn;
- }
- };
-
- var urlSanitizationNode = $document[0].createElement('a'),
- startSymbol = $interpolate.startSymbol(),
- endSymbol = $interpolate.endSymbol(),
- denormalizeTemplate = (startSymbol == '{{' || endSymbol == '}}')
- ? identity
- : function denormalizeTemplate(template) {
- return template.replace(/\{\{/g, startSymbol).replace(/}}/g, endSymbol);
- };
-
-
- return compile;
-
- //================================
-
- function compile($compileNodes, transcludeFn, maxPriority) {
- if (!($compileNodes instanceof jqLite)) {
- // jquery always rewraps, whereas we need to preserve the original selector so that we can modify it.
- $compileNodes = jqLite($compileNodes);
- }
- // We can not compile top level text elements since text nodes can be merged and we will
- // not be able to attach scope data to them, so we will wrap them in
- forEach($compileNodes, function(node, index){
- if (node.nodeType == 3 /* text node */ && node.nodeValue.match(/\S+/) /* non-empty */ ) {
- $compileNodes[index] = jqLite(node).wrap('').parent()[0];
- }
- });
- var compositeLinkFn = compileNodes($compileNodes, transcludeFn, $compileNodes, maxPriority);
- return function publicLinkFn(scope, cloneConnectFn){
- assertArg(scope, 'scope');
- // important!!: we must call our jqLite.clone() since the jQuery one is trying to be smart
- // and sometimes changes the structure of the DOM.
- var $linkNode = cloneConnectFn
- ? JQLitePrototype.clone.call($compileNodes) // IMPORTANT!!!
- : $compileNodes;
-
- // Attach scope only to non-text nodes.
- for(var i = 0, ii = $linkNode.length; i
- addDirective(directives,
- directiveNormalize(nodeName_(node).toLowerCase()), 'E', maxPriority);
-
- // iterate over the attributes
- for (var attr, name, nName, value, nAttrs = node.attributes,
- j = 0, jj = nAttrs && nAttrs.length; j < jj; j++) {
- attr = nAttrs[j];
- if (attr.specified) {
- name = attr.name;
- nName = directiveNormalize(name.toLowerCase());
- attrsMap[nName] = name;
- attrs[nName] = value = trim((msie && name == 'href')
- ? decodeURIComponent(node.getAttribute(name, 2))
- : attr.value);
- if (getBooleanAttrName(node, nName)) {
- attrs[nName] = true; // presence means true
- }
- addAttrInterpolateDirective(node, directives, value, nName);
- addDirective(directives, nName, 'A', maxPriority);
- }
- }
-
- // use class as directive
- className = node.className;
- if (isString(className) && className !== '') {
- while (match = CLASS_DIRECTIVE_REGEXP.exec(className)) {
- nName = directiveNormalize(match[2]);
- if (addDirective(directives, nName, 'C', maxPriority)) {
- attrs[nName] = trim(match[3]);
- }
- className = className.substr(match.index + match[0].length);
- }
- }
- break;
- case 3: /* Text Node */
- addTextInterpolateDirective(directives, node.nodeValue);
- break;
- case 8: /* Comment */
- try {
- match = COMMENT_DIRECTIVE_REGEXP.exec(node.nodeValue);
- if (match) {
- nName = directiveNormalize(match[1]);
- if (addDirective(directives, nName, 'M', maxPriority)) {
- attrs[nName] = trim(match[2]);
- }
- }
- } catch (e) {
- // turns out that under some circumstances IE9 throws errors when one attempts to read comment's node value.
- // Just ignore it and continue. (Can't seem to reproduce in test case.)
- }
- break;
- }
-
- directives.sort(byPriority);
- return directives;
- }
-
-
- /**
- * Once the directives have been collected their compile functions is executed. This method
- * is responsible for inlining directive templates as well as terminating the application
- * of the directives if the terminal directive has been reached..
- *
- * @param {Array} directives Array of collected directives to execute their compile function.
- * this needs to be pre-sorted by priority order.
- * @param {Node} compileNode The raw DOM node to apply the compile functions to
- * @param {Object} templateAttrs The shared attribute function
- * @param {function(angular.Scope[, cloneAttachFn]} transcludeFn A linking function, where the
- * scope argument is auto-generated to the new child of the transcluded parent scope.
- * @param {DOMElement} $rootElement If we are working on the root of the compile tree then this
- * argument has the root jqLite array so that we can replace widgets on it.
- * @returns linkFn
- */
- function applyDirectivesToNode(directives, compileNode, templateAttrs, transcludeFn, $rootElement) {
- var terminalPriority = -Number.MAX_VALUE,
- preLinkFns = [],
- postLinkFns = [],
- newScopeDirective = null,
- newIsolateScopeDirective = null,
- templateDirective = null,
- $compileNode = templateAttrs.$$element = jqLite(compileNode),
- directive,
- directiveName,
- $template,
- transcludeDirective,
- childTranscludeFn = transcludeFn,
- controllerDirectives,
- linkFn,
- directiveValue;
-
- // executes all directives on the current element
- for(var i = 0, ii = directives.length; i < ii; i++) {
- directive = directives[i];
- $template = undefined;
-
- if (terminalPriority > directive.priority) {
- break; // prevent further processing of directives
- }
-
- if (directiveValue = directive.scope) {
- assertNoDuplicate('isolated scope', newIsolateScopeDirective, directive, $compileNode);
- if (isObject(directiveValue)) {
- safeAddClass($compileNode, 'ng-isolate-scope');
- newIsolateScopeDirective = directive;
- }
- safeAddClass($compileNode, 'ng-scope');
- newScopeDirective = newScopeDirective || directive;
- }
-
- directiveName = directive.name;
-
- if (directiveValue = directive.controller) {
- controllerDirectives = controllerDirectives || {};
- assertNoDuplicate("'" + directiveName + "' controller",
- controllerDirectives[directiveName], directive, $compileNode);
- controllerDirectives[directiveName] = directive;
- }
-
- if (directiveValue = directive.transclude) {
- assertNoDuplicate('transclusion', transcludeDirective, directive, $compileNode);
- transcludeDirective = directive;
- terminalPriority = directive.priority;
- if (directiveValue == 'element') {
- $template = jqLite(compileNode);
- $compileNode = templateAttrs.$$element =
- jqLite(document.createComment(' ' + directiveName + ': ' + templateAttrs[directiveName] + ' '));
- compileNode = $compileNode[0];
- replaceWith($rootElement, jqLite($template[0]), compileNode);
- childTranscludeFn = compile($template, transcludeFn, terminalPriority);
- } else {
- $template = jqLite(JQLiteClone(compileNode)).contents();
- $compileNode.html(''); // clear contents
- childTranscludeFn = compile($template, transcludeFn);
- }
- }
-
- if ((directiveValue = directive.template)) {
- assertNoDuplicate('template', templateDirective, directive, $compileNode);
- templateDirective = directive;
- directiveValue = denormalizeTemplate(directiveValue);
-
- if (directive.replace) {
- $template = jqLite('
' +
- trim(directiveValue) +
- '
').contents();
- compileNode = $template[0];
-
- if ($template.length != 1 || compileNode.nodeType !== 1) {
- throw new Error(MULTI_ROOT_TEMPLATE_ERROR + directiveValue);
- }
-
- replaceWith($rootElement, $compileNode, compileNode);
-
- var newTemplateAttrs = {$attr: {}};
-
- // combine directives from the original node and from the template:
- // - take the array of directives for this element
- // - split it into two parts, those that were already applied and those that weren't
- // - collect directives from the template, add them to the second group and sort them
- // - append the second group with new directives to the first group
- directives = directives.concat(
- collectDirectives(
- compileNode,
- directives.splice(i + 1, directives.length - (i + 1)),
- newTemplateAttrs
- )
- );
- mergeTemplateAttributes(templateAttrs, newTemplateAttrs);
-
- ii = directives.length;
- } else {
- $compileNode.html(directiveValue);
- }
- }
-
- if (directive.templateUrl) {
- assertNoDuplicate('template', templateDirective, directive, $compileNode);
- templateDirective = directive;
- nodeLinkFn = compileTemplateUrl(directives.splice(i, directives.length - i),
- nodeLinkFn, $compileNode, templateAttrs, $rootElement, directive.replace,
- childTranscludeFn);
- ii = directives.length;
- } else if (directive.compile) {
- try {
- linkFn = directive.compile($compileNode, templateAttrs, childTranscludeFn);
- if (isFunction(linkFn)) {
- addLinkFns(null, linkFn);
- } else if (linkFn) {
- addLinkFns(linkFn.pre, linkFn.post);
- }
- } catch (e) {
- $exceptionHandler(e, startingTag($compileNode));
- }
- }
-
- if (directive.terminal) {
- nodeLinkFn.terminal = true;
- terminalPriority = Math.max(terminalPriority, directive.priority);
- }
-
- }
-
- nodeLinkFn.scope = newScopeDirective && newScopeDirective.scope;
- nodeLinkFn.transclude = transcludeDirective && childTranscludeFn;
-
- // might be normal or delayed nodeLinkFn depending on if templateUrl is present
- return nodeLinkFn;
-
- ////////////////////
-
- function addLinkFns(pre, post) {
- if (pre) {
- pre.require = directive.require;
- preLinkFns.push(pre);
- }
- if (post) {
- post.require = directive.require;
- postLinkFns.push(post);
- }
- }
-
-
- function getControllers(require, $element) {
- var value, retrievalMethod = 'data', optional = false;
- if (isString(require)) {
- while((value = require.charAt(0)) == '^' || value == '?') {
- require = require.substr(1);
- if (value == '^') {
- retrievalMethod = 'inheritedData';
- }
- optional = optional || value == '?';
- }
- value = $element[retrievalMethod]('$' + require + 'Controller');
- if (!value && !optional) {
- throw Error("No controller: " + require);
- }
- return value;
- } else if (isArray(require)) {
- value = [];
- forEach(require, function(require) {
- value.push(getControllers(require, $element));
- });
- }
- return value;
- }
-
-
- function nodeLinkFn(childLinkFn, scope, linkNode, $rootElement, boundTranscludeFn) {
- var attrs, $element, i, ii, linkFn, controller;
-
- if (compileNode === linkNode) {
- attrs = templateAttrs;
- } else {
- attrs = shallowCopy(templateAttrs, new Attributes(jqLite(linkNode), templateAttrs.$attr));
- }
- $element = attrs.$$element;
-
- if (newIsolateScopeDirective) {
- var LOCAL_REGEXP = /^\s*([@=&])\s*(\w*)\s*$/;
-
- var parentScope = scope.$parent || scope;
-
- forEach(newIsolateScopeDirective.scope, function(definiton, scopeName) {
- var match = definiton.match(LOCAL_REGEXP) || [],
- attrName = match[2]|| scopeName,
- mode = match[1], // @, =, or &
- lastValue,
- parentGet, parentSet;
-
- scope.$$isolateBindings[scopeName] = mode + attrName;
-
- switch (mode) {
-
- case '@': {
- attrs.$observe(attrName, function(value) {
- scope[scopeName] = value;
- });
- attrs.$$observers[attrName].$$scope = parentScope;
- break;
- }
-
- case '=': {
- parentGet = $parse(attrs[attrName]);
- parentSet = parentGet.assign || function() {
- // reset the change, or we will throw this exception on every $digest
- lastValue = scope[scopeName] = parentGet(parentScope);
- throw Error(NON_ASSIGNABLE_MODEL_EXPRESSION + attrs[attrName] +
- ' (directive: ' + newIsolateScopeDirective.name + ')');
- };
- lastValue = scope[scopeName] = parentGet(parentScope);
- scope.$watch(function parentValueWatch() {
- var parentValue = parentGet(parentScope);
-
- if (parentValue !== scope[scopeName]) {
- // we are out of sync and need to copy
- if (parentValue !== lastValue) {
- // parent changed and it has precedence
- lastValue = scope[scopeName] = parentValue;
- } else {
- // if the parent can be assigned then do so
- parentSet(parentScope, parentValue = lastValue = scope[scopeName]);
- }
- }
- return parentValue;
- });
- break;
- }
-
- case '&': {
- parentGet = $parse(attrs[attrName]);
- scope[scopeName] = function(locals) {
- return parentGet(parentScope, locals);
- }
- break;
- }
-
- default: {
- throw Error('Invalid isolate scope definition for directive ' +
- newIsolateScopeDirective.name + ': ' + definiton);
- }
- }
- });
- }
-
- if (controllerDirectives) {
- forEach(controllerDirectives, function(directive) {
- var locals = {
- $scope: scope,
- $element: $element,
- $attrs: attrs,
- $transclude: boundTranscludeFn
- };
-
- controller = directive.controller;
- if (controller == '@') {
- controller = attrs[directive.name];
- }
-
- $element.data(
- '$' + directive.name + 'Controller',
- $controller(controller, locals));
- });
- }
-
- // PRELINKING
- for(i = 0, ii = preLinkFns.length; i < ii; i++) {
- try {
- linkFn = preLinkFns[i];
- linkFn(scope, $element, attrs,
- linkFn.require && getControllers(linkFn.require, $element));
- } catch (e) {
- $exceptionHandler(e, startingTag($element));
- }
- }
-
- // RECURSION
- childLinkFn && childLinkFn(scope, linkNode.childNodes, undefined, boundTranscludeFn);
-
- // POSTLINKING
- for(i = 0, ii = postLinkFns.length; i < ii; i++) {
- try {
- linkFn = postLinkFns[i];
- linkFn(scope, $element, attrs,
- linkFn.require && getControllers(linkFn.require, $element));
- } catch (e) {
- $exceptionHandler(e, startingTag($element));
- }
- }
- }
- }
-
-
- /**
- * looks up the directive and decorates it with exception handling and proper parameters. We
- * call this the boundDirective.
- *
- * @param {string} name name of the directive to look up.
- * @param {string} location The directive must be found in specific format.
- * String containing any of theses characters:
- *
- * * `E`: element name
- * * `A': attribute
- * * `C`: class
- * * `M`: comment
- * @returns true if directive was added.
- */
- function addDirective(tDirectives, name, location, maxPriority) {
- var match = false;
- if (hasDirectives.hasOwnProperty(name)) {
- for(var directive, directives = $injector.get(name + Suffix),
- i = 0, ii = directives.length; i directive.priority) &&
- directive.restrict.indexOf(location) != -1) {
- tDirectives.push(directive);
- match = true;
- }
- } catch(e) { $exceptionHandler(e); }
- }
- }
- return match;
- }
-
-
- /**
- * When the element is replaced with HTML template then the new attributes
- * on the template need to be merged with the existing attributes in the DOM.
- * The desired effect is to have both of the attributes present.
- *
- * @param {object} dst destination attributes (original DOM)
- * @param {object} src source attributes (from the directive template)
- */
- function mergeTemplateAttributes(dst, src) {
- var srcAttr = src.$attr,
- dstAttr = dst.$attr,
- $element = dst.$$element;
-
- // reapply the old attributes to the new element
- forEach(dst, function(value, key) {
- if (key.charAt(0) != '$') {
- if (src[key]) {
- value += (key === 'style' ? ';' : ' ') + src[key];
- }
- dst.$set(key, value, true, srcAttr[key]);
- }
- });
-
- // copy the new attributes on the old attrs object
- forEach(src, function(value, key) {
- if (key == 'class') {
- safeAddClass($element, value);
- dst['class'] = (dst['class'] ? dst['class'] + ' ' : '') + value;
- } else if (key == 'style') {
- $element.attr('style', $element.attr('style') + ';' + value);
- } else if (key.charAt(0) != '$' && !dst.hasOwnProperty(key)) {
- dst[key] = value;
- dstAttr[key] = srcAttr[key];
- }
- });
- }
-
-
- function compileTemplateUrl(directives, beforeTemplateNodeLinkFn, $compileNode, tAttrs,
- $rootElement, replace, childTranscludeFn) {
- var linkQueue = [],
- afterTemplateNodeLinkFn,
- afterTemplateChildLinkFn,
- beforeTemplateCompileNode = $compileNode[0],
- origAsyncDirective = directives.shift(),
- // The fact that we have to copy and patch the directive seems wrong!
- derivedSyncDirective = extend({}, origAsyncDirective, {
- controller: null, templateUrl: null, transclude: null, scope: null
- });
-
- $compileNode.html('');
-
- $http.get(origAsyncDirective.templateUrl, {cache: $templateCache}).
- success(function(content) {
- var compileNode, tempTemplateAttrs, $template;
-
- content = denormalizeTemplate(content);
-
- if (replace) {
- $template = jqLite('
' + trim(content) + '
').contents();
- compileNode = $template[0];
-
- if ($template.length != 1 || compileNode.nodeType !== 1) {
- throw new Error(MULTI_ROOT_TEMPLATE_ERROR + content);
- }
-
- tempTemplateAttrs = {$attr: {}};
- replaceWith($rootElement, $compileNode, compileNode);
- collectDirectives(compileNode, directives, tempTemplateAttrs);
- mergeTemplateAttributes(tAttrs, tempTemplateAttrs);
- } else {
- compileNode = beforeTemplateCompileNode;
- $compileNode.html(content);
- }
-
- directives.unshift(derivedSyncDirective);
- afterTemplateNodeLinkFn = applyDirectivesToNode(directives, compileNode, tAttrs, childTranscludeFn);
- afterTemplateChildLinkFn = compileNodes($compileNode[0].childNodes, childTranscludeFn);
-
-
- while(linkQueue.length) {
- var controller = linkQueue.pop(),
- linkRootElement = linkQueue.pop(),
- beforeTemplateLinkNode = linkQueue.pop(),
- scope = linkQueue.pop(),
- linkNode = compileNode;
-
- if (beforeTemplateLinkNode !== beforeTemplateCompileNode) {
- // it was cloned therefore we have to clone as well.
- linkNode = JQLiteClone(compileNode);
- replaceWith(linkRootElement, jqLite(beforeTemplateLinkNode), linkNode);
- }
-
- afterTemplateNodeLinkFn(function() {
- beforeTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, linkNode, $rootElement, controller);
- }, scope, linkNode, $rootElement, controller);
- }
- linkQueue = null;
- }).
- error(function(response, code, headers, config) {
- throw Error('Failed to load template: ' + config.url);
- });
-
- return function delayedNodeLinkFn(ignoreChildLinkFn, scope, node, rootElement, controller) {
- if (linkQueue) {
- linkQueue.push(scope);
- linkQueue.push(node);
- linkQueue.push(rootElement);
- linkQueue.push(controller);
- } else {
- afterTemplateNodeLinkFn(function() {
- beforeTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, node, rootElement, controller);
- }, scope, node, rootElement, controller);
- }
- };
- }
-
-
- /**
- * Sorting function for bound directives.
- */
- function byPriority(a, b) {
- return b.priority - a.priority;
- }
-
-
- function assertNoDuplicate(what, previousDirective, directive, element) {
- if (previousDirective) {
- throw Error('Multiple directives [' + previousDirective.name + ', ' +
- directive.name + '] asking for ' + what + ' on: ' + startingTag(element));
- }
- }
-
-
- function addTextInterpolateDirective(directives, text) {
- var interpolateFn = $interpolate(text, true);
- if (interpolateFn) {
- directives.push({
- priority: 0,
- compile: valueFn(function textInterpolateLinkFn(scope, node) {
- var parent = node.parent(),
- bindings = parent.data('$binding') || [];
- bindings.push(interpolateFn);
- safeAddClass(parent.data('$binding', bindings), 'ng-binding');
- scope.$watch(interpolateFn, function interpolateFnWatchAction(value) {
- node[0].nodeValue = value;
- });
- })
- });
- }
- }
-
-
- function addAttrInterpolateDirective(node, directives, value, name) {
- var interpolateFn = $interpolate(value, true);
-
- // no interpolation found -> ignore
- if (!interpolateFn) return;
-
-
- directives.push({
- priority: 100,
- compile: valueFn(function attrInterpolateLinkFn(scope, element, attr) {
- var $$observers = (attr.$$observers || (attr.$$observers = {}));
-
- if (name === 'class') {
- // we need to interpolate classes again, in the case the element was replaced
- // and therefore the two class attrs got merged - we want to interpolate the result
- interpolateFn = $interpolate(attr[name], true);
- }
-
- attr[name] = undefined;
- ($$observers[name] || ($$observers[name] = [])).$$inter = true;
- (attr.$$observers && attr.$$observers[name].$$scope || scope).
- $watch(interpolateFn, function interpolateFnWatchAction(value) {
- attr.$set(name, value);
- });
- })
- });
- }
-
-
- /**
- * This is a special jqLite.replaceWith, which can replace items which
- * have no parents, provided that the containing jqLite collection is provided.
- *
- * @param {JqLite=} $rootElement The root of the compile tree. Used so that we can replace nodes
- * in the root of the tree.
- * @param {JqLite} $element The jqLite element which we are going to replace. We keep the shell,
- * but replace its DOM node reference.
- * @param {Node} newNode The new DOM node.
- */
- function replaceWith($rootElement, $element, newNode) {
- var oldNode = $element[0],
- parent = oldNode.parentNode,
- i, ii;
-
- if ($rootElement) {
- for(i = 0, ii = $rootElement.length; i < ii; i++) {
- if ($rootElement[i] == oldNode) {
- $rootElement[i] = newNode;
- break;
- }
- }
- }
-
- if (parent) {
- parent.replaceChild(newNode, oldNode);
- }
-
- newNode[jqLite.expando] = oldNode[jqLite.expando];
- $element[0] = newNode;
- }
- }];
-}
-
-var PREFIX_REGEXP = /^(x[\:\-_]|data[\:\-_])/i;
-/**
- * Converts all accepted directives format into proper directive name.
- * All of these will become 'myDirective':
- * my:DiRective
- * my-directive
- * x-my-directive
- * data-my:directive
- *
- * Also there is special case for Moz prefix starting with upper case letter.
- * @param name Name to normalize
- */
-function directiveNormalize(name) {
- return camelCase(name.replace(PREFIX_REGEXP, ''));
-}
-
-/**
- * @ngdoc object
- * @name ng.$compile.directive.Attributes
- * @description
- *
- * A shared object between directive compile / linking functions which contains normalized DOM element
- * attributes. The the values reflect current binding state `{{ }}`. The normalization is needed
- * since all of these are treated as equivalent in Angular:
- *
- *
- */
-
-/**
- * @ngdoc property
- * @name ng.$compile.directive.Attributes#$attr
- * @propertyOf ng.$compile.directive.Attributes
- * @returns {object} A map of DOM element attribute names to the normalized name. This is
- * needed to do reverse lookup from normalized name back to actual name.
- */
-
-
-/**
- * @ngdoc function
- * @name ng.$compile.directive.Attributes#$set
- * @methodOf ng.$compile.directive.Attributes
- * @function
- *
- * @description
- * Set DOM element attribute value.
- *
- *
- * @param {string} name Normalized element attribute name of the property to modify. The name is
- * revers translated using the {@link ng.$compile.directive.Attributes#$attr $attr}
- * property to the original name.
- * @param {string} value Value to set the attribute to.
- */
-
-
-
-/**
- * Closure compiler type information
- */
-
-function nodesetLinkingFn(
- /* angular.Scope */ scope,
- /* NodeList */ nodeList,
- /* Element */ rootElement,
- /* function(Function) */ boundTranscludeFn
-){}
-
-function directiveLinkingFn(
- /* nodesetLinkingFn */ nodesetLinkingFn,
- /* angular.Scope */ scope,
- /* Node */ node,
- /* Element */ rootElement,
- /* function(Function) */ boundTranscludeFn
-){}
-
-/**
- * @ngdoc object
- * @name ng.$controllerProvider
- * @description
- * The {@link ng.$controller $controller service} is used by Angular to create new
- * controllers.
- *
- * This provider allows controller registration via the
- * {@link ng.$controllerProvider#register register} method.
- */
-function $ControllerProvider() {
- var controllers = {};
-
-
- /**
- * @ngdoc function
- * @name ng.$controllerProvider#register
- * @methodOf ng.$controllerProvider
- * @param {string} name Controller name
- * @param {Function|Array} constructor Controller constructor fn (optionally decorated with DI
- * annotations in the array notation).
- */
- this.register = function(name, constructor) {
- if (isObject(name)) {
- extend(controllers, name)
- } else {
- controllers[name] = constructor;
- }
- };
-
-
- this.$get = ['$injector', '$window', function($injector, $window) {
-
- /**
- * @ngdoc function
- * @name ng.$controller
- * @requires $injector
- *
- * @param {Function|string} constructor If called with a function then it's considered to be the
- * controller constructor function. Otherwise it's considered to be a string which is used
- * to retrieve the controller constructor using the following steps:
- *
- * * check if a controller with given name is registered via `$controllerProvider`
- * * check if evaluating the string on the current scope returns a constructor
- * * check `window[constructor]` on the global `window` object
- *
- * @param {Object} locals Injection locals for Controller.
- * @return {Object} Instance of given controller.
- *
- * @description
- * `$controller` service is responsible for instantiating controllers.
- *
- * It's just a simple call to {@link AUTO.$injector $injector}, but extracted into
- * a service, so that one can override this service with {@link https://gist.github.com/1649788
- * BC version}.
- */
- return function(constructor, locals) {
- if(isString(constructor)) {
- var name = constructor;
- constructor = controllers.hasOwnProperty(name)
- ? controllers[name]
- : getter(locals.$scope, name, true) || getter($window, name, true);
-
- assertArgFn(constructor, name, true);
- }
-
- return $injector.instantiate(constructor, locals);
- };
- }];
-}
-
-/**
- * @ngdoc object
- * @name ng.$document
- * @requires $window
- *
- * @description
- * A {@link angular.element jQuery (lite)}-wrapped reference to the browser's `window.document`
- * element.
- */
-function $DocumentProvider(){
- this.$get = ['$window', function(window){
- return jqLite(window.document);
- }];
-}
-
-/**
- * @ngdoc function
- * @name ng.$exceptionHandler
- * @requires $log
- *
- * @description
- * Any uncaught exception in angular expressions is delegated to this service.
- * The default implementation simply delegates to `$log.error` which logs it into
- * the browser console.
- *
- * In unit tests, if `angular-mocks.js` is loaded, this service is overridden by
- * {@link ngMock.$exceptionHandler mock $exceptionHandler} which aids in testing.
- *
- * @param {Error} exception Exception associated with the error.
- * @param {string=} cause optional information about the context in which
- * the error was thrown.
- *
- */
-function $ExceptionHandlerProvider() {
- this.$get = ['$log', function($log){
- return function(exception, cause) {
- $log.error.apply($log, arguments);
- };
- }];
-}
-
-/**
- * @ngdoc object
- * @name ng.$interpolateProvider
- * @function
- *
- * @description
- *
- * Used for configuring the interpolation markup. Defaults to `{{` and `}}`.
- */
-function $InterpolateProvider() {
- var startSymbol = '{{';
- var endSymbol = '}}';
-
- /**
- * @ngdoc method
- * @name ng.$interpolateProvider#startSymbol
- * @methodOf ng.$interpolateProvider
- * @description
- * Symbol to denote start of expression in the interpolated string. Defaults to `{{`.
- *
- * @param {string=} value new value to set the starting symbol to.
- * @returns {string|self} Returns the symbol when used as getter and self if used as setter.
- */
- this.startSymbol = function(value){
- if (value) {
- startSymbol = value;
- return this;
- } else {
- return startSymbol;
- }
- };
-
- /**
- * @ngdoc method
- * @name ng.$interpolateProvider#endSymbol
- * @methodOf ng.$interpolateProvider
- * @description
- * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`.
- *
- * @param {string=} value new value to set the ending symbol to.
- * @returns {string|self} Returns the symbol when used as getter and self if used as setter.
- */
- this.endSymbol = function(value){
- if (value) {
- endSymbol = value;
- return this;
- } else {
- return endSymbol;
- }
- };
-
-
- this.$get = ['$parse', function($parse) {
- var startSymbolLength = startSymbol.length,
- endSymbolLength = endSymbol.length;
-
- /**
- * @ngdoc function
- * @name ng.$interpolate
- * @function
- *
- * @requires $parse
- *
- * @description
- *
- * Compiles a string with markup into an interpolation function. This service is used by the
- * HTML {@link ng.$compile $compile} service for data binding. See
- * {@link ng.$interpolateProvider $interpolateProvider} for configuring the
- * interpolation markup.
- *
- *
-
- var $interpolate = ...; // injected
- var exp = $interpolate('Hello {{name}}!');
- expect(exp({name:'Angular'}).toEqual('Hello Angular!');
-
- *
- *
- * @param {string} text The text with markup to interpolate.
- * @param {boolean=} mustHaveExpression if set to true then the interpolation string must have
- * embedded expression in order to return an interpolation function. Strings with no
- * embedded expression will return null for the interpolation function.
- * @returns {function(context)} an interpolation function which is used to compute the interpolated
- * string. The function has these parameters:
- *
- * * `context`: an object against which any expressions embedded in the strings are evaluated
- * against.
- *
- */
- function $interpolate(text, mustHaveExpression) {
- var startIndex,
- endIndex,
- index = 0,
- parts = [],
- length = text.length,
- hasInterpolation = false,
- fn,
- exp,
- concat = [];
-
- while(index < length) {
- if ( ((startIndex = text.indexOf(startSymbol, index)) != -1) &&
- ((endIndex = text.indexOf(endSymbol, startIndex + startSymbolLength)) != -1) ) {
- (index != startIndex) && parts.push(text.substring(index, startIndex));
- parts.push(fn = $parse(exp = text.substring(startIndex + startSymbolLength, endIndex)));
- fn.exp = exp;
- index = endIndex + endSymbolLength;
- hasInterpolation = true;
- } else {
- // we did not find anything, so we have to add the remainder to the parts array
- (index != length) && parts.push(text.substring(index));
- index = length;
- }
- }
-
- if (!(length = parts.length)) {
- // we added, nothing, must have been an empty string.
- parts.push('');
- length = 1;
- }
-
- if (!mustHaveExpression || hasInterpolation) {
- concat.length = length;
- fn = function(context) {
- for(var i = 0, ii = length, part; i html5 url
- } else {
- return composeProtocolHostPort(match.protocol, match.host, match.port) +
- pathPrefixFromBase(basePath) + match.hash.substr(hashPrefix.length);
- }
-}
-
-
-function convertToHashbangUrl(url, basePath, hashPrefix) {
- var match = matchUrl(url);
-
- // already hashbang url
- if (decodeURIComponent(match.path) == basePath && !isUndefined(match.hash) &&
- match.hash.indexOf(hashPrefix) === 0) {
- return url;
- // convert html5 url -> hashbang url
- } else {
- var search = match.search && '?' + match.search || '',
- hash = match.hash && '#' + match.hash || '',
- pathPrefix = pathPrefixFromBase(basePath),
- path = match.path.substr(pathPrefix.length);
-
- if (match.path.indexOf(pathPrefix) !== 0) {
- throw Error('Invalid url "' + url + '", missing path prefix "' + pathPrefix + '" !');
- }
-
- return composeProtocolHostPort(match.protocol, match.host, match.port) + basePath +
- '#' + hashPrefix + path + search + hash;
- }
-}
-
-
-/**
- * LocationUrl represents an url
- * This object is exposed as $location service when HTML5 mode is enabled and supported
- *
- * @constructor
- * @param {string} url HTML5 url
- * @param {string} pathPrefix
- */
-function LocationUrl(url, pathPrefix, appBaseUrl) {
- pathPrefix = pathPrefix || '';
-
- /**
- * Parse given html5 (regular) url string into properties
- * @param {string} newAbsoluteUrl HTML5 url
- * @private
- */
- this.$$parse = function(newAbsoluteUrl) {
- var match = matchUrl(newAbsoluteUrl, this);
-
- if (match.path.indexOf(pathPrefix) !== 0) {
- throw Error('Invalid url "' + newAbsoluteUrl + '", missing path prefix "' + pathPrefix + '" !');
- }
-
- this.$$path = decodeURIComponent(match.path.substr(pathPrefix.length));
- this.$$search = parseKeyValue(match.search);
- this.$$hash = match.hash && decodeURIComponent(match.hash) || '';
-
- this.$$compose();
- };
-
- /**
- * Compose url and update `absUrl` property
- * @private
- */
- this.$$compose = function() {
- var search = toKeyValue(this.$$search),
- hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';
-
- this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;
- this.$$absUrl = composeProtocolHostPort(this.$$protocol, this.$$host, this.$$port) +
- pathPrefix + this.$$url;
- };
-
-
- this.$$rewriteAppUrl = function(absoluteLinkUrl) {
- if(absoluteLinkUrl.indexOf(appBaseUrl) == 0) {
- return absoluteLinkUrl;
- }
- }
-
-
- this.$$parse(url);
-}
-
-
-/**
- * LocationHashbangUrl represents url
- * This object is exposed as $location service when html5 history api is disabled or not supported
- *
- * @constructor
- * @param {string} url Legacy url
- * @param {string} hashPrefix Prefix for hash part (containing path and search)
- */
-function LocationHashbangUrl(url, hashPrefix, appBaseUrl) {
- var basePath;
-
- /**
- * Parse given hashbang url into properties
- * @param {string} url Hashbang url
- * @private
- */
- this.$$parse = function(url) {
- var match = matchUrl(url, this);
-
-
- if (match.hash && match.hash.indexOf(hashPrefix) !== 0) {
- throw Error('Invalid url "' + url + '", missing hash prefix "' + hashPrefix + '" !');
- }
-
- basePath = match.path + (match.search ? '?' + match.search : '');
- match = HASH_MATCH.exec((match.hash || '').substr(hashPrefix.length));
- if (match[1]) {
- this.$$path = (match[1].charAt(0) == '/' ? '' : '/') + decodeURIComponent(match[1]);
- } else {
- this.$$path = '';
- }
-
- this.$$search = parseKeyValue(match[3]);
- this.$$hash = match[5] && decodeURIComponent(match[5]) || '';
-
- this.$$compose();
- };
-
- /**
- * Compose hashbang url and update `absUrl` property
- * @private
- */
- this.$$compose = function() {
- var search = toKeyValue(this.$$search),
- hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';
-
- this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;
- this.$$absUrl = composeProtocolHostPort(this.$$protocol, this.$$host, this.$$port) +
- basePath + (this.$$url ? '#' + hashPrefix + this.$$url : '');
- };
-
- this.$$rewriteAppUrl = function(absoluteLinkUrl) {
- if(absoluteLinkUrl.indexOf(appBaseUrl) == 0) {
- return absoluteLinkUrl;
- }
- }
-
-
- this.$$parse(url);
-}
-
-
-LocationUrl.prototype = {
-
- /**
- * Has any change been replacing ?
- * @private
- */
- $$replace: false,
-
- /**
- * @ngdoc method
- * @name ng.$location#absUrl
- * @methodOf ng.$location
- *
- * @description
- * This method is getter only.
- *
- * Return full url representation with all segments encoded according to rules specified in
- * {@link http://www.ietf.org/rfc/rfc3986.txt RFC 3986}.
- *
- * @return {string} full url
- */
- absUrl: locationGetter('$$absUrl'),
-
- /**
- * @ngdoc method
- * @name ng.$location#url
- * @methodOf ng.$location
- *
- * @description
- * This method is getter / setter.
- *
- * Return url (e.g. `/path?a=b#hash`) when called without any parameter.
- *
- * Change path, search and hash, when called with parameter and return `$location`.
- *
- * @param {string=} url New url without base prefix (e.g. `/path?a=b#hash`)
- * @return {string} url
- */
- url: function(url, replace) {
- if (isUndefined(url))
- return this.$$url;
-
- var match = PATH_MATCH.exec(url);
- if (match[1]) this.path(decodeURIComponent(match[1]));
- if (match[2] || match[1]) this.search(match[3] || '');
- this.hash(match[5] || '', replace);
-
- return this;
- },
-
- /**
- * @ngdoc method
- * @name ng.$location#protocol
- * @methodOf ng.$location
- *
- * @description
- * This method is getter only.
- *
- * Return protocol of current url.
- *
- * @return {string} protocol of current url
- */
- protocol: locationGetter('$$protocol'),
-
- /**
- * @ngdoc method
- * @name ng.$location#host
- * @methodOf ng.$location
- *
- * @description
- * This method is getter only.
- *
- * Return host of current url.
- *
- * @return {string} host of current url.
- */
- host: locationGetter('$$host'),
-
- /**
- * @ngdoc method
- * @name ng.$location#port
- * @methodOf ng.$location
- *
- * @description
- * This method is getter only.
- *
- * Return port of current url.
- *
- * @return {Number} port
- */
- port: locationGetter('$$port'),
-
- /**
- * @ngdoc method
- * @name ng.$location#path
- * @methodOf ng.$location
- *
- * @description
- * This method is getter / setter.
- *
- * Return path of current url when called without any parameter.
- *
- * Change path when called with parameter and return `$location`.
- *
- * Note: Path should always begin with forward slash (/), this method will add the forward slash
- * if it is missing.
- *
- * @param {string=} path New path
- * @return {string} path
- */
- path: locationGetterSetter('$$path', function(path) {
- return path.charAt(0) == '/' ? path : '/' + path;
- }),
-
- /**
- * @ngdoc method
- * @name ng.$location#search
- * @methodOf ng.$location
- *
- * @description
- * This method is getter / setter.
- *
- * Return search part (as object) of current url when called without any parameter.
- *
- * Change search part when called with parameter and return `$location`.
- *
- * @param {string|object=} search New search params - string or hash object
- * @param {string=} paramValue If `search` is a string, then `paramValue` will override only a
- * single search parameter. If the value is `null`, the parameter will be deleted.
- *
- * @return {string} search
- */
- search: function(search, paramValue) {
- if (isUndefined(search))
- return this.$$search;
-
- if (isDefined(paramValue)) {
- if (paramValue === null) {
- delete this.$$search[search];
- } else {
- this.$$search[search] = paramValue;
- }
- } else {
- this.$$search = isString(search) ? parseKeyValue(search) : search;
- }
-
- this.$$compose();
- return this;
- },
-
- /**
- * @ngdoc method
- * @name ng.$location#hash
- * @methodOf ng.$location
- *
- * @description
- * This method is getter / setter.
- *
- * Return hash fragment when called without any parameter.
- *
- * Change hash fragment when called with parameter and return `$location`.
- *
- * @param {string=} hash New hash fragment
- * @return {string} hash
- */
- hash: locationGetterSetter('$$hash', identity),
-
- /**
- * @ngdoc method
- * @name ng.$location#replace
- * @methodOf ng.$location
- *
- * @description
- * If called, all changes to $location during current `$digest` will be replacing current history
- * record, instead of adding new one.
- */
- replace: function() {
- this.$$replace = true;
- return this;
- }
-};
-
-LocationHashbangUrl.prototype = inherit(LocationUrl.prototype);
-
-function LocationHashbangInHtml5Url(url, hashPrefix, appBaseUrl, baseExtra) {
- LocationHashbangUrl.apply(this, arguments);
-
-
- this.$$rewriteAppUrl = function(absoluteLinkUrl) {
- if (absoluteLinkUrl.indexOf(appBaseUrl) == 0) {
- return appBaseUrl + baseExtra + '#' + hashPrefix + absoluteLinkUrl.substr(appBaseUrl.length);
- }
- }
-}
-
-LocationHashbangInHtml5Url.prototype = inherit(LocationHashbangUrl.prototype);
-
-function locationGetter(property) {
- return function() {
- return this[property];
- };
-}
-
-
-function locationGetterSetter(property, preprocess) {
- return function(value) {
- if (isUndefined(value))
- return this[property];
-
- this[property] = preprocess(value);
- this.$$compose();
-
- return this;
- };
-}
-
-
-/**
- * @ngdoc object
- * @name ng.$location
- *
- * @requires $browser
- * @requires $sniffer
- * @requires $rootElement
- *
- * @description
- * The $location service parses the URL in the browser address bar (based on the
- * {@link https://developer.mozilla.org/en/window.location window.location}) and makes the URL
- * available to your application. Changes to the URL in the address bar are reflected into
- * $location service and changes to $location are reflected into the browser address bar.
- *
- * **The $location service:**
- *
- * - Exposes the current URL in the browser address bar, so you can
- * - Watch and observe the URL.
- * - Change the URL.
- * - Synchronizes the URL with the browser when the user
- * - Changes the address bar.
- * - Clicks the back or forward button (or clicks a History link).
- * - Clicks on a link.
- * - Represents the URL object as a set of methods (protocol, host, port, path, search, hash).
- *
- * For more information see {@link guide/dev_guide.services.$location Developer Guide: Angular
- * Services: Using $location}
- */
-
-/**
- * @ngdoc object
- * @name ng.$locationProvider
- * @description
- * Use the `$locationProvider` to configure how the application deep linking paths are stored.
- */
-function $LocationProvider(){
- var hashPrefix = '',
- html5Mode = false;
-
- /**
- * @ngdoc property
- * @name ng.$locationProvider#hashPrefix
- * @methodOf ng.$locationProvider
- * @description
- * @param {string=} prefix Prefix for hash part (containing path and search)
- * @returns {*} current value if used as getter or itself (chaining) if used as setter
- */
- this.hashPrefix = function(prefix) {
- if (isDefined(prefix)) {
- hashPrefix = prefix;
- return this;
- } else {
- return hashPrefix;
- }
- };
-
- /**
- * @ngdoc property
- * @name ng.$locationProvider#html5Mode
- * @methodOf ng.$locationProvider
- * @description
- * @param {string=} mode Use HTML5 strategy if available.
- * @returns {*} current value if used as getter or itself (chaining) if used as setter
- */
- this.html5Mode = function(mode) {
- if (isDefined(mode)) {
- html5Mode = mode;
- return this;
- } else {
- return html5Mode;
- }
- };
-
- this.$get = ['$rootScope', '$browser', '$sniffer', '$rootElement',
- function( $rootScope, $browser, $sniffer, $rootElement) {
- var $location,
- basePath,
- pathPrefix,
- initUrl = $browser.url(),
- initUrlParts = matchUrl(initUrl),
- appBaseUrl;
-
- if (html5Mode) {
- basePath = $browser.baseHref() || '/';
- pathPrefix = pathPrefixFromBase(basePath);
- appBaseUrl =
- composeProtocolHostPort(initUrlParts.protocol, initUrlParts.host, initUrlParts.port) +
- pathPrefix + '/';
-
- if ($sniffer.history) {
- $location = new LocationUrl(
- convertToHtml5Url(initUrl, basePath, hashPrefix),
- pathPrefix, appBaseUrl);
- } else {
- $location = new LocationHashbangInHtml5Url(
- convertToHashbangUrl(initUrl, basePath, hashPrefix),
- hashPrefix, appBaseUrl, basePath.substr(pathPrefix.length + 1));
- }
- } else {
- appBaseUrl =
- composeProtocolHostPort(initUrlParts.protocol, initUrlParts.host, initUrlParts.port) +
- (initUrlParts.path || '') +
- (initUrlParts.search ? ('?' + initUrlParts.search) : '') +
- '#' + hashPrefix + '/';
-
- $location = new LocationHashbangUrl(initUrl, hashPrefix, appBaseUrl);
- }
-
- $rootElement.bind('click', function(event) {
- // TODO(vojta): rewrite link when opening in new tab/window (in legacy browser)
- // currently we open nice url link and redirect then
-
- if (event.ctrlKey || event.metaKey || event.which == 2) return;
-
- var elm = jqLite(event.target);
-
- // traverse the DOM up to find first A tag
- while (lowercase(elm[0].nodeName) !== 'a') {
- // ignore rewriting if no A tag (reached root element, or no parent - removed from document)
- if (elm[0] === $rootElement[0] || !(elm = elm.parent())[0]) return;
- }
-
- var absHref = elm.prop('href'),
- rewrittenUrl = $location.$$rewriteAppUrl(absHref);
-
- if (absHref && !elm.attr('target') && rewrittenUrl) {
- // update location manually
- $location.$$parse(rewrittenUrl);
- $rootScope.$apply();
- event.preventDefault();
- // hack to work around FF6 bug 684208 when scenario runner clicks on links
- window.angular['ff-684208-preventDefault'] = true;
- }
- });
-
-
- // rewrite hashbang url <> html5 url
- if ($location.absUrl() != initUrl) {
- $browser.url($location.absUrl(), true);
- }
-
- // update $location when $browser url changes
- $browser.onUrlChange(function(newUrl) {
- if ($location.absUrl() != newUrl) {
- $rootScope.$evalAsync(function() {
- var oldUrl = $location.absUrl();
-
- $location.$$parse(newUrl);
- afterLocationChange(oldUrl);
- });
- if (!$rootScope.$$phase) $rootScope.$digest();
- }
- });
-
- // update browser
- var changeCounter = 0;
- $rootScope.$watch(function $locationWatch() {
- var oldUrl = $browser.url();
- var currentReplace = $location.$$replace;
-
- if (!changeCounter || oldUrl != $location.absUrl()) {
- changeCounter++;
- $rootScope.$evalAsync(function() {
- if ($rootScope.$broadcast('$locationChangeStart', $location.absUrl(), oldUrl).
- defaultPrevented) {
- $location.$$parse(oldUrl);
- } else {
- $browser.url($location.absUrl(), currentReplace);
- afterLocationChange(oldUrl);
- }
- });
- }
- $location.$$replace = false;
-
- return changeCounter;
- });
-
- return $location;
-
- function afterLocationChange(oldUrl) {
- $rootScope.$broadcast('$locationChangeSuccess', $location.absUrl(), oldUrl);
- }
-}];
-}
-
-/**
- * @ngdoc object
- * @name ng.$log
- * @requires $window
- *
- * @description
- * Simple service for logging. Default implementation writes the message
- * into the browser's console (if present).
- *
- * The main purpose of this service is to simplify debugging and troubleshooting.
- *
- * @example
-
-
- function LogCtrl($scope, $log) {
- $scope.$log = $log;
- $scope.message = 'Hello World!';
- }
-
-
-
-
Reload this page with open console, enter text and hit the log button...
- Message:
-
-
-
-
-
-
-
-
- */
-
-function $LogProvider(){
- this.$get = ['$window', function($window){
- return {
- /**
- * @ngdoc method
- * @name ng.$log#log
- * @methodOf ng.$log
- *
- * @description
- * Write a log message
- */
- log: consoleLog('log'),
-
- /**
- * @ngdoc method
- * @name ng.$log#warn
- * @methodOf ng.$log
- *
- * @description
- * Write a warning message
- */
- warn: consoleLog('warn'),
-
- /**
- * @ngdoc method
- * @name ng.$log#info
- * @methodOf ng.$log
- *
- * @description
- * Write an information message
- */
- info: consoleLog('info'),
-
- /**
- * @ngdoc method
- * @name ng.$log#error
- * @methodOf ng.$log
- *
- * @description
- * Write an error message
- */
- error: consoleLog('error')
- };
-
- function formatError(arg) {
- if (arg instanceof Error) {
- if (arg.stack) {
- arg = (arg.message && arg.stack.indexOf(arg.message) === -1)
- ? 'Error: ' + arg.message + '\n' + arg.stack
- : arg.stack;
- } else if (arg.sourceURL) {
- arg = arg.message + '\n' + arg.sourceURL + ':' + arg.line;
- }
- }
- return arg;
- }
-
- function consoleLog(type) {
- var console = $window.console || {},
- logFn = console[type] || console.log || noop;
-
- if (logFn.apply) {
- return function() {
- var args = [];
- forEach(arguments, function(arg) {
- args.push(formatError(arg));
- });
- return logFn.apply(console, args);
- };
- }
-
- // we are IE which either doesn't have window.console => this is noop and we do nothing,
- // or we are IE where console.log doesn't have apply so we log at least first 2 args
- return function(arg1, arg2) {
- logFn(arg1, arg2);
- }
- }
- }];
-}
-
-var OPERATORS = {
- 'null':function(){return null;},
- 'true':function(){return true;},
- 'false':function(){return false;},
- undefined:noop,
- '+':function(self, locals, a,b){
- a=a(self, locals); b=b(self, locals);
- if (isDefined(a)) {
- if (isDefined(b)) {
- return a + b;
- }
- return a;
- }
- return isDefined(b)?b:undefined;},
- '-':function(self, locals, a,b){a=a(self, locals); b=b(self, locals); return (isDefined(a)?a:0)-(isDefined(b)?b:0);},
- '*':function(self, locals, a,b){return a(self, locals)*b(self, locals);},
- '/':function(self, locals, a,b){return a(self, locals)/b(self, locals);},
- '%':function(self, locals, a,b){return a(self, locals)%b(self, locals);},
- '^':function(self, locals, a,b){return a(self, locals)^b(self, locals);},
- '=':noop,
- '==':function(self, locals, a,b){return a(self, locals)==b(self, locals);},
- '!=':function(self, locals, a,b){return a(self, locals)!=b(self, locals);},
- '<':function(self, locals, a,b){return a(self, locals)':function(self, locals, a,b){return a(self, locals)>b(self, locals);},
- '<=':function(self, locals, a,b){return a(self, locals)<=b(self, locals);},
- '>=':function(self, locals, a,b){return a(self, locals)>=b(self, locals);},
- '&&':function(self, locals, a,b){return a(self, locals)&&b(self, locals);},
- '||':function(self, locals, a,b){return a(self, locals)||b(self, locals);},
- '&':function(self, locals, a,b){return a(self, locals)&b(self, locals);},
-// '|':function(self, locals, a,b){return a|b;},
- '|':function(self, locals, a,b){return b(self, locals)(self, locals, a(self, locals));},
- '!':function(self, locals, a){return !a(self, locals);}
-};
-var ESCAPE = {"n":"\n", "f":"\f", "r":"\r", "t":"\t", "v":"\v", "'":"'", '"':'"'};
-
-function lex(text, csp){
- var tokens = [],
- token,
- index = 0,
- json = [],
- ch,
- lastCh = ':'; // can start regexp
-
- while (index < text.length) {
- ch = text.charAt(index);
- if (is('"\'')) {
- readString(ch);
- } else if (isNumber(ch) || is('.') && isNumber(peek())) {
- readNumber();
- } else if (isIdent(ch)) {
- readIdent();
- // identifiers can only be if the preceding char was a { or ,
- if (was('{,') && json[0]=='{' &&
- (token=tokens[tokens.length-1])) {
- token.json = token.text.indexOf('.') == -1;
- }
- } else if (is('(){}[].,;:')) {
- tokens.push({
- index:index,
- text:ch,
- json:(was(':[,') && is('{[')) || is('}]:,')
- });
- if (is('{[')) json.unshift(ch);
- if (is('}]')) json.shift();
- index++;
- } else if (isWhitespace(ch)) {
- index++;
- continue;
- } else {
- var ch2 = ch + peek(),
- fn = OPERATORS[ch],
- fn2 = OPERATORS[ch2];
- if (fn2) {
- tokens.push({index:index, text:ch2, fn:fn2});
- index += 2;
- } else if (fn) {
- tokens.push({index:index, text:ch, fn:fn, json: was('[,:') && is('+-')});
- index += 1;
- } else {
- throwError("Unexpected next character ", index, index+1);
- }
- }
- lastCh = ch;
- }
- return tokens;
-
- function is(chars) {
- return chars.indexOf(ch) != -1;
- }
-
- function was(chars) {
- return chars.indexOf(lastCh) != -1;
- }
-
- function peek() {
- return index + 1 < text.length ? text.charAt(index + 1) : false;
- }
- function isNumber(ch) {
- return '0' <= ch && ch <= '9';
- }
- function isWhitespace(ch) {
- return ch == ' ' || ch == '\r' || ch == '\t' ||
- ch == '\n' || ch == '\v' || ch == '\u00A0'; // IE treats non-breaking space as \u00A0
- }
- function isIdent(ch) {
- return 'a' <= ch && ch <= 'z' ||
- 'A' <= ch && ch <= 'Z' ||
- '_' == ch || ch == '$';
- }
- function isExpOperator(ch) {
- return ch == '-' || ch == '+' || isNumber(ch);
- }
-
- function throwError(error, start, end) {
- end = end || index;
- throw Error("Lexer Error: " + error + " at column" +
- (isDefined(start)
- ? "s " + start + "-" + index + " [" + text.substring(start, end) + "]"
- : " " + end) +
- " in expression [" + text + "].");
- }
-
- function readNumber() {
- var number = "";
- var start = index;
- while (index < text.length) {
- var ch = lowercase(text.charAt(index));
- if (ch == '.' || isNumber(ch)) {
- number += ch;
- } else {
- var peekCh = peek();
- if (ch == 'e' && isExpOperator(peekCh)) {
- number += ch;
- } else if (isExpOperator(ch) &&
- peekCh && isNumber(peekCh) &&
- number.charAt(number.length - 1) == 'e') {
- number += ch;
- } else if (isExpOperator(ch) &&
- (!peekCh || !isNumber(peekCh)) &&
- number.charAt(number.length - 1) == 'e') {
- throwError('Invalid exponent');
- } else {
- break;
- }
- }
- index++;
- }
- number = 1 * number;
- tokens.push({index:start, text:number, json:true,
- fn:function() {return number;}});
- }
- function readIdent() {
- var ident = "",
- start = index,
- lastDot, peekIndex, methodName;
-
- while (index < text.length) {
- var ch = text.charAt(index);
- if (ch == '.' || isIdent(ch) || isNumber(ch)) {
- if (ch == '.') lastDot = index;
- ident += ch;
- } else {
- break;
- }
- index++;
- }
-
- //check if this is not a method invocation and if it is back out to last dot
- if (lastDot) {
- peekIndex = index;
- while(peekIndex < text.length) {
- var ch = text.charAt(peekIndex);
- if (ch == '(') {
- methodName = ident.substr(lastDot - start + 1);
- ident = ident.substr(0, lastDot - start);
- index = peekIndex;
- break;
- }
- if(isWhitespace(ch)) {
- peekIndex++;
- } else {
- break;
- }
- }
- }
-
-
- var token = {
- index:start,
- text:ident
- };
-
- if (OPERATORS.hasOwnProperty(ident)) {
- token.fn = token.json = OPERATORS[ident];
- } else {
- var getter = getterFn(ident, csp);
- token.fn = extend(function(self, locals) {
- return (getter(self, locals));
- }, {
- assign: function(self, value) {
- return setter(self, ident, value);
- }
- });
- }
-
- tokens.push(token);
-
- if (methodName) {
- tokens.push({
- index:lastDot,
- text: '.',
- json: false
- });
- tokens.push({
- index: lastDot + 1,
- text: methodName,
- json: false
- });
- }
- }
-
- function readString(quote) {
- var start = index;
- index++;
- var string = "";
- var rawString = quote;
- var escape = false;
- while (index < text.length) {
- var ch = text.charAt(index);
- rawString += ch;
- if (escape) {
- if (ch == 'u') {
- var hex = text.substring(index + 1, index + 5);
- if (!hex.match(/[\da-f]{4}/i))
- throwError( "Invalid unicode escape [\\u" + hex + "]");
- index += 4;
- string += String.fromCharCode(parseInt(hex, 16));
- } else {
- var rep = ESCAPE[ch];
- if (rep) {
- string += rep;
- } else {
- string += ch;
- }
- }
- escape = false;
- } else if (ch == '\\') {
- escape = true;
- } else if (ch == quote) {
- index++;
- tokens.push({
- index:start,
- text:rawString,
- string:string,
- json:true,
- fn:function() { return string; }
- });
- return;
- } else {
- string += ch;
- }
- index++;
- }
- throwError("Unterminated quote", start);
- }
-}
-
-/////////////////////////////////////////
-
-function parser(text, json, $filter, csp){
- var ZERO = valueFn(0),
- value,
- tokens = lex(text, csp),
- assignment = _assignment,
- functionCall = _functionCall,
- fieldAccess = _fieldAccess,
- objectIndex = _objectIndex,
- filterChain = _filterChain;
-
- if(json){
- // The extra level of aliasing is here, just in case the lexer misses something, so that
- // we prevent any accidental execution in JSON.
- assignment = logicalOR;
- functionCall =
- fieldAccess =
- objectIndex =
- filterChain =
- function() { throwError("is not valid json", {text:text, index:0}); };
- value = primary();
- } else {
- value = statements();
- }
- if (tokens.length !== 0) {
- throwError("is an unexpected token", tokens[0]);
- }
- return value;
-
- ///////////////////////////////////
- function throwError(msg, token) {
- throw Error("Syntax Error: Token '" + token.text +
- "' " + msg + " at column " +
- (token.index + 1) + " of the expression [" +
- text + "] starting at [" + text.substring(token.index) + "].");
- }
-
- function peekToken() {
- if (tokens.length === 0)
- throw Error("Unexpected end of expression: " + text);
- return tokens[0];
- }
-
- function peek(e1, e2, e3, e4) {
- if (tokens.length > 0) {
- var token = tokens[0];
- var t = token.text;
- if (t==e1 || t==e2 || t==e3 || t==e4 ||
- (!e1 && !e2 && !e3 && !e4)) {
- return token;
- }
- }
- return false;
- }
-
- function expect(e1, e2, e3, e4){
- var token = peek(e1, e2, e3, e4);
- if (token) {
- if (json && !token.json) {
- throwError("is not valid json", token);
- }
- tokens.shift();
- return token;
- }
- return false;
- }
-
- function consume(e1){
- if (!expect(e1)) {
- throwError("is unexpected, expecting [" + e1 + "]", peek());
- }
- }
-
- function unaryFn(fn, right) {
- return function(self, locals) {
- return fn(self, locals, right);
- };
- }
-
- function binaryFn(left, fn, right) {
- return function(self, locals) {
- return fn(self, locals, left, right);
- };
- }
-
- function statements() {
- var statements = [];
- while(true) {
- if (tokens.length > 0 && !peek('}', ')', ';', ']'))
- statements.push(filterChain());
- if (!expect(';')) {
- // optimize for the common case where there is only one statement.
- // TODO(size): maybe we should not support multiple statements?
- return statements.length == 1
- ? statements[0]
- : function(self, locals){
- var value;
- for ( var i = 0; i < statements.length; i++) {
- var statement = statements[i];
- if (statement)
- value = statement(self, locals);
- }
- return value;
- };
- }
- }
- }
-
- function _filterChain() {
- var left = expression();
- var token;
- while(true) {
- if ((token = expect('|'))) {
- left = binaryFn(left, token.fn, filter());
- } else {
- return left;
- }
- }
- }
-
- function filter() {
- var token = expect();
- var fn = $filter(token.text);
- var argsFn = [];
- while(true) {
- if ((token = expect(':'))) {
- argsFn.push(expression());
- } else {
- var fnInvoke = function(self, locals, input){
- var args = [input];
- for ( var i = 0; i < argsFn.length; i++) {
- args.push(argsFn[i](self, locals));
- }
- return fn.apply(self, args);
- };
- return function() {
- return fnInvoke;
- };
- }
- }
- }
-
- function expression() {
- return assignment();
- }
-
- function _assignment() {
- var left = logicalOR();
- var right;
- var token;
- if ((token = expect('='))) {
- if (!left.assign) {
- throwError("implies assignment but [" +
- text.substring(0, token.index) + "] can not be assigned to", token);
- }
- right = logicalOR();
- return function(self, locals){
- return left.assign(self, right(self, locals), locals);
- };
- } else {
- return left;
- }
- }
-
- function logicalOR() {
- var left = logicalAND();
- var token;
- while(true) {
- if ((token = expect('||'))) {
- left = binaryFn(left, token.fn, logicalAND());
- } else {
- return left;
- }
- }
- }
-
- function logicalAND() {
- var left = equality();
- var token;
- if ((token = expect('&&'))) {
- left = binaryFn(left, token.fn, logicalAND());
- }
- return left;
- }
-
- function equality() {
- var left = relational();
- var token;
- if ((token = expect('==','!='))) {
- left = binaryFn(left, token.fn, equality());
- }
- return left;
- }
-
- function relational() {
- var left = additive();
- var token;
- if ((token = expect('<', '>', '<=', '>='))) {
- left = binaryFn(left, token.fn, relational());
- }
- return left;
- }
-
- function additive() {
- var left = multiplicative();
- var token;
- while ((token = expect('+','-'))) {
- left = binaryFn(left, token.fn, multiplicative());
- }
- return left;
- }
-
- function multiplicative() {
- var left = unary();
- var token;
- while ((token = expect('*','/','%'))) {
- left = binaryFn(left, token.fn, unary());
- }
- return left;
- }
-
- function unary() {
- var token;
- if (expect('+')) {
- return primary();
- } else if ((token = expect('-'))) {
- return binaryFn(ZERO, token.fn, unary());
- } else if ((token = expect('!'))) {
- return unaryFn(token.fn, unary());
- } else {
- return primary();
- }
- }
-
-
- function primary() {
- var primary;
- if (expect('(')) {
- primary = filterChain();
- consume(')');
- } else if (expect('[')) {
- primary = arrayDeclaration();
- } else if (expect('{')) {
- primary = object();
- } else {
- var token = expect();
- primary = token.fn;
- if (!primary) {
- throwError("not a primary expression", token);
- }
- }
-
- var next, context;
- while ((next = expect('(', '[', '.'))) {
- if (next.text === '(') {
- primary = functionCall(primary, context);
- context = null;
- } else if (next.text === '[') {
- context = primary;
- primary = objectIndex(primary);
- } else if (next.text === '.') {
- context = primary;
- primary = fieldAccess(primary);
- } else {
- throwError("IMPOSSIBLE");
- }
- }
- return primary;
- }
-
- function _fieldAccess(object) {
- var field = expect().text;
- var getter = getterFn(field, csp);
- return extend(
- function(self, locals) {
- return getter(object(self, locals), locals);
- },
- {
- assign:function(self, value, locals) {
- return setter(object(self, locals), field, value);
- }
- }
- );
- }
-
- function _objectIndex(obj) {
- var indexFn = expression();
- consume(']');
- return extend(
- function(self, locals){
- var o = obj(self, locals),
- i = indexFn(self, locals),
- v, p;
-
- if (!o) return undefined;
- v = o[i];
- if (v && v.then) {
- p = v;
- if (!('$$v' in v)) {
- p.$$v = undefined;
- p.then(function(val) { p.$$v = val; });
- }
- v = v.$$v;
- }
- return v;
- }, {
- assign:function(self, value, locals){
- return obj(self, locals)[indexFn(self, locals)] = value;
- }
- });
- }
-
- function _functionCall(fn, contextGetter) {
- var argsFn = [];
- if (peekToken().text != ')') {
- do {
- argsFn.push(expression());
- } while (expect(','));
- }
- consume(')');
- return function(self, locals){
- var args = [],
- context = contextGetter ? contextGetter(self, locals) : self;
-
- for ( var i = 0; i < argsFn.length; i++) {
- args.push(argsFn[i](self, locals));
- }
- var fnPtr = fn(self, locals) || noop;
- // IE stupidity!
- return fnPtr.apply
- ? fnPtr.apply(context, args)
- : fnPtr(args[0], args[1], args[2], args[3], args[4]);
- };
- }
-
- // This is used with json array declaration
- function arrayDeclaration () {
- var elementFns = [];
- if (peekToken().text != ']') {
- do {
- elementFns.push(expression());
- } while (expect(','));
- }
- consume(']');
- return function(self, locals){
- var array = [];
- for ( var i = 0; i < elementFns.length; i++) {
- array.push(elementFns[i](self, locals));
- }
- return array;
- };
- }
-
- function object () {
- var keyValues = [];
- if (peekToken().text != '}') {
- do {
- var token = expect(),
- key = token.string || token.text;
- consume(":");
- var value = expression();
- keyValues.push({key:key, value:value});
- } while (expect(','));
- }
- consume('}');
- return function(self, locals){
- var object = {};
- for ( var i = 0; i < keyValues.length; i++) {
- var keyValue = keyValues[i];
- var value = keyValue.value(self, locals);
- object[keyValue.key] = value;
- }
- return object;
- };
- }
-}
-
-//////////////////////////////////////////////////
-// Parser helper functions
-//////////////////////////////////////////////////
-
-function setter(obj, path, setValue) {
- var element = path.split('.');
- for (var i = 0; element.length > 1; i++) {
- var key = element.shift();
- var propertyObj = obj[key];
- if (!propertyObj) {
- propertyObj = {};
- obj[key] = propertyObj;
- }
- obj = propertyObj;
- }
- obj[element.shift()] = setValue;
- return setValue;
-}
-
-/**
- * Return the value accesible from the object by path. Any undefined traversals are ignored
- * @param {Object} obj starting object
- * @param {string} path path to traverse
- * @param {boolean=true} bindFnToScope
- * @returns value as accesbile by path
- */
-//TODO(misko): this function needs to be removed
-function getter(obj, path, bindFnToScope) {
- if (!path) return obj;
- var keys = path.split('.');
- var key;
- var lastInstance = obj;
- var len = keys.length;
-
- for (var i = 0; i < len; i++) {
- key = keys[i];
- if (obj) {
- obj = (lastInstance = obj)[key];
- }
- }
- if (!bindFnToScope && isFunction(obj)) {
- return bind(lastInstance, obj);
- }
- return obj;
-}
-
-var getterFnCache = {};
-
-/**
- * Implementation of the "Black Hole" variant from:
- * - http://jsperf.com/angularjs-parse-getter/4
- * - http://jsperf.com/path-evaluation-simplified/7
- */
-function cspSafeGetterFn(key0, key1, key2, key3, key4) {
- return function(scope, locals) {
- var pathVal = (locals && locals.hasOwnProperty(key0)) ? locals : scope,
- promise;
-
- if (pathVal === null || pathVal === undefined) return pathVal;
-
- pathVal = pathVal[key0];
- if (pathVal && pathVal.then) {
- if (!("$$v" in pathVal)) {
- promise = pathVal;
- promise.$$v = undefined;
- promise.then(function(val) { promise.$$v = val; });
- }
- pathVal = pathVal.$$v;
- }
- if (!key1 || pathVal === null || pathVal === undefined) return pathVal;
-
- pathVal = pathVal[key1];
- if (pathVal && pathVal.then) {
- if (!("$$v" in pathVal)) {
- promise = pathVal;
- promise.$$v = undefined;
- promise.then(function(val) { promise.$$v = val; });
- }
- pathVal = pathVal.$$v;
- }
- if (!key2 || pathVal === null || pathVal === undefined) return pathVal;
-
- pathVal = pathVal[key2];
- if (pathVal && pathVal.then) {
- if (!("$$v" in pathVal)) {
- promise = pathVal;
- promise.$$v = undefined;
- promise.then(function(val) { promise.$$v = val; });
- }
- pathVal = pathVal.$$v;
- }
- if (!key3 || pathVal === null || pathVal === undefined) return pathVal;
-
- pathVal = pathVal[key3];
- if (pathVal && pathVal.then) {
- if (!("$$v" in pathVal)) {
- promise = pathVal;
- promise.$$v = undefined;
- promise.then(function(val) { promise.$$v = val; });
- }
- pathVal = pathVal.$$v;
- }
- if (!key4 || pathVal === null || pathVal === undefined) return pathVal;
-
- pathVal = pathVal[key4];
- if (pathVal && pathVal.then) {
- if (!("$$v" in pathVal)) {
- promise = pathVal;
- promise.$$v = undefined;
- promise.then(function(val) { promise.$$v = val; });
- }
- pathVal = pathVal.$$v;
- }
- return pathVal;
- };
-};
-
-function getterFn(path, csp) {
- if (getterFnCache.hasOwnProperty(path)) {
- return getterFnCache[path];
- }
-
- var pathKeys = path.split('.'),
- pathKeysLength = pathKeys.length,
- fn;
-
- if (csp) {
- fn = (pathKeysLength < 6)
- ? cspSafeGetterFn(pathKeys[0], pathKeys[1], pathKeys[2], pathKeys[3], pathKeys[4])
- : function(scope, locals) {
- var i = 0, val
- do {
- val = cspSafeGetterFn(
- pathKeys[i++], pathKeys[i++], pathKeys[i++], pathKeys[i++], pathKeys[i++]
- )(scope, locals);
-
- locals = undefined; // clear after first iteration
- scope = val;
- } while (i < pathKeysLength);
- return val;
- }
- } else {
- var code = 'var l, fn, p;\n';
- forEach(pathKeys, function(key, index) {
- code += 'if(s === null || s === undefined) return s;\n' +
- 'l=s;\n' +
- 's='+ (index
- // we simply dereference 's' on any .dot notation
- ? 's'
- // but if we are first then we check locals first, and if so read it first
- : '((k&&k.hasOwnProperty("' + key + '"))?k:s)') + '["' + key + '"]' + ';\n' +
- 'if (s && s.then) {\n' +
- ' if (!("$$v" in s)) {\n' +
- ' p=s;\n' +
- ' p.$$v = undefined;\n' +
- ' p.then(function(v) {p.$$v=v;});\n' +
- '}\n' +
- ' s=s.$$v\n' +
- '}\n';
- });
- code += 'return s;';
- fn = Function('s', 'k', code); // s=scope, k=locals
- fn.toString = function() { return code; };
- }
-
- return getterFnCache[path] = fn;
-}
-
-///////////////////////////////////
-
-/**
- * @ngdoc function
- * @name ng.$parse
- * @function
- *
- * @description
- *
- * Converts Angular {@link guide/expression expression} into a function.
- *
- *
- *
- *
- * @param {string} expression String expression to compile.
- * @returns {function(context, locals)} a function which represents the compiled expression:
- *
- * * `context` – `{object}` – an object against which any expressions embedded in the strings
- * are evaluated against (tipically a scope object).
- * * `locals` – `{object=}` – local variables context object, useful for overriding values in
- * `context`.
- *
- * The return function also has an `assign` property, if the expression is assignable, which
- * allows one to set values to expressions.
- *
- */
-function $ParseProvider() {
- var cache = {};
- this.$get = ['$filter', '$sniffer', function($filter, $sniffer) {
- return function(exp) {
- switch(typeof exp) {
- case 'string':
- return cache.hasOwnProperty(exp)
- ? cache[exp]
- : cache[exp] = parser(exp, false, $filter, $sniffer.csp);
- case 'function':
- return exp;
- default:
- return noop;
- }
- };
- }];
-}
-
-/**
- * @ngdoc service
- * @name ng.$q
- * @requires $rootScope
- *
- * @description
- * A promise/deferred implementation inspired by [Kris Kowal's Q](https://github.com/kriskowal/q).
- *
- * [The CommonJS Promise proposal](http://wiki.commonjs.org/wiki/Promises) describes a promise as an
- * interface for interacting with an object that represents the result of an action that is
- * performed asynchronously, and may or may not be finished at any given point in time.
- *
- * From the perspective of dealing with error handling, deferred and promise APIs are to
- * asynchronous programming what `try`, `catch` and `throw` keywords are to synchronous programming.
- *
- *
- * // for the purpose of this example let's assume that variables `$q` and `scope` are
- * // available in the current lexical scope (they could have been injected or passed in).
- *
- * function asyncGreet(name) {
- * var deferred = $q.defer();
- *
- * setTimeout(function() {
- * // since this fn executes async in a future turn of the event loop, we need to wrap
- * // our code into an $apply call so that the model changes are properly observed.
- * scope.$apply(function() {
- * if (okToGreet(name)) {
- * deferred.resolve('Hello, ' + name + '!');
- * } else {
- * deferred.reject('Greeting ' + name + ' is not allowed.');
- * }
- * });
- * }, 1000);
- *
- * return deferred.promise;
- * }
- *
- * var promise = asyncGreet('Robin Hood');
- * promise.then(function(greeting) {
- * alert('Success: ' + greeting);
- * }, function(reason) {
- * alert('Failed: ' + reason);
- * });
- *
- *
- * At first it might not be obvious why this extra complexity is worth the trouble. The payoff
- * comes in the way of
- * [guarantees that promise and deferred APIs make](https://github.com/kriskowal/uncommonjs/blob/master/promises/specification.md).
- *
- * Additionally the promise api allows for composition that is very hard to do with the
- * traditional callback ([CPS](http://en.wikipedia.org/wiki/Continuation-passing_style)) approach.
- * For more on this please see the [Q documentation](https://github.com/kriskowal/q) especially the
- * section on serial or parallel joining of promises.
- *
- *
- * # The Deferred API
- *
- * A new instance of deferred is constructed by calling `$q.defer()`.
- *
- * The purpose of the deferred object is to expose the associated Promise instance as well as APIs
- * that can be used for signaling the successful or unsuccessful completion of the task.
- *
- * **Methods**
- *
- * - `resolve(value)` – resolves the derived promise with the `value`. If the value is a rejection
- * constructed via `$q.reject`, the promise will be rejected instead.
- * - `reject(reason)` – rejects the derived promise with the `reason`. This is equivalent to
- * resolving it with a rejection constructed via `$q.reject`.
- *
- * **Properties**
- *
- * - promise – `{Promise}` – promise object associated with this deferred.
- *
- *
- * # The Promise API
- *
- * A new promise instance is created when a deferred instance is created and can be retrieved by
- * calling `deferred.promise`.
- *
- * The purpose of the promise object is to allow for interested parties to get access to the result
- * of the deferred task when it completes.
- *
- * **Methods**
- *
- * - `then(successCallback, errorCallback)` – regardless of when the promise was or will be resolved
- * or rejected calls one of the success or error callbacks asynchronously as soon as the result
- * is available. The callbacks are called with a single argument the result or rejection reason.
- *
- * This method *returns a new promise* which is resolved or rejected via the return value of the
- * `successCallback` or `errorCallback`.
- *
- *
- * # Chaining promises
- *
- * Because calling `then` api of a promise returns a new derived promise, it is easily possible
- * to create a chain of promises:
- *
- *
- * promiseB = promiseA.then(function(result) {
- * return result + 1;
- * });
- *
- * // promiseB will be resolved immediately after promiseA is resolved and its value will be
- * // the result of promiseA incremented by 1
- *
- *
- * It is possible to create chains of any length and since a promise can be resolved with another
- * promise (which will defer its resolution further), it is possible to pause/defer resolution of
- * the promises at any point in the chain. This makes it possible to implement powerful apis like
- * $http's response interceptors.
- *
- *
- * # Differences between Kris Kowal's Q and $q
- *
- * There are three main differences:
- *
- * - $q is integrated with the {@link ng.$rootScope.Scope} Scope model observation
- * mechanism in angular, which means faster propagation of resolution or rejection into your
- * models and avoiding unnecessary browser repaints, which would result in flickering UI.
- * - $q promises are recognized by the templating engine in angular, which means that in templates
- * you can treat promises attached to a scope as if they were the resulting values.
- * - Q has many more features that $q, but that comes at a cost of bytes. $q is tiny, but contains
- * all the important functionality needed for common async tasks.
- *
- * # Testing
- *
- *
- * it('should simulate promise', inject(function($q, $rootScope) {
- * var deferred = $q.defer();
- * var promise = deferred.promise;
- * var resolvedValue;
- *
- * promise.then(function(value) { resolvedValue = value; });
- * expect(resolvedValue).toBeUndefined();
- *
- * // Simulate resolving of promise
- * deferred.resolve(123);
- * // Note that the 'then' function does not get called synchronously.
- * // This is because we want the promise API to always be async, whether or not
- * // it got called synchronously or asynchronously.
- * expect(resolvedValue).toBeUndefined();
- *
- * // Propagate promise resolution to 'then' functions using $apply().
- * $rootScope.$apply();
- * expect(resolvedValue).toEqual(123);
- * });
- *
- */
-function $QProvider() {
-
- this.$get = ['$rootScope', '$exceptionHandler', function($rootScope, $exceptionHandler) {
- return qFactory(function(callback) {
- $rootScope.$evalAsync(callback);
- }, $exceptionHandler);
- }];
-}
-
-
-/**
- * Constructs a promise manager.
- *
- * @param {function(function)} nextTick Function for executing functions in the next turn.
- * @param {function(...*)} exceptionHandler Function into which unexpected exceptions are passed for
- * debugging purposes.
- * @returns {object} Promise manager.
- */
-function qFactory(nextTick, exceptionHandler) {
-
- /**
- * @ngdoc
- * @name ng.$q#defer
- * @methodOf ng.$q
- * @description
- * Creates a `Deferred` object which represents a task which will finish in the future.
- *
- * @returns {Deferred} Returns a new instance of deferred.
- */
- var defer = function() {
- var pending = [],
- value, deferred;
-
- deferred = {
-
- resolve: function(val) {
- if (pending) {
- var callbacks = pending;
- pending = undefined;
- value = ref(val);
-
- if (callbacks.length) {
- nextTick(function() {
- var callback;
- for (var i = 0, ii = callbacks.length; i < ii; i++) {
- callback = callbacks[i];
- value.then(callback[0], callback[1]);
- }
- });
- }
- }
- },
-
-
- reject: function(reason) {
- deferred.resolve(reject(reason));
- },
-
-
- promise: {
- then: function(callback, errback) {
- var result = defer();
-
- var wrappedCallback = function(value) {
- try {
- result.resolve((callback || defaultCallback)(value));
- } catch(e) {
- exceptionHandler(e);
- result.reject(e);
- }
- };
-
- var wrappedErrback = function(reason) {
- try {
- result.resolve((errback || defaultErrback)(reason));
- } catch(e) {
- exceptionHandler(e);
- result.reject(e);
- }
- };
-
- if (pending) {
- pending.push([wrappedCallback, wrappedErrback]);
- } else {
- value.then(wrappedCallback, wrappedErrback);
- }
-
- return result.promise;
- }
- }
- };
-
- return deferred;
- };
-
-
- var ref = function(value) {
- if (value && value.then) return value;
- return {
- then: function(callback) {
- var result = defer();
- nextTick(function() {
- result.resolve(callback(value));
- });
- return result.promise;
- }
- };
- };
-
-
- /**
- * @ngdoc
- * @name ng.$q#reject
- * @methodOf ng.$q
- * @description
- * Creates a promise that is resolved as rejected with the specified `reason`. This api should be
- * used to forward rejection in a chain of promises. If you are dealing with the last promise in
- * a promise chain, you don't need to worry about it.
- *
- * When comparing deferreds/promises to the familiar behavior of try/catch/throw, think of
- * `reject` as the `throw` keyword in JavaScript. This also means that if you "catch" an error via
- * a promise error callback and you want to forward the error to the promise derived from the
- * current promise, you have to "rethrow" the error by returning a rejection constructed via
- * `reject`.
- *
- *
- * promiseB = promiseA.then(function(result) {
- * // success: do something and resolve promiseB
- * // with the old or a new result
- * return result;
- * }, function(reason) {
- * // error: handle the error if possible and
- * // resolve promiseB with newPromiseOrValue,
- * // otherwise forward the rejection to promiseB
- * if (canHandle(reason)) {
- * // handle the error and recover
- * return newPromiseOrValue;
- * }
- * return $q.reject(reason);
- * });
- *
- *
- * @param {*} reason Constant, message, exception or an object representing the rejection reason.
- * @returns {Promise} Returns a promise that was already resolved as rejected with the `reason`.
- */
- var reject = function(reason) {
- return {
- then: function(callback, errback) {
- var result = defer();
- nextTick(function() {
- result.resolve((errback || defaultErrback)(reason));
- });
- return result.promise;
- }
- };
- };
-
-
- /**
- * @ngdoc
- * @name ng.$q#when
- * @methodOf ng.$q
- * @description
- * Wraps an object that might be a value or a (3rd party) then-able promise into a $q promise.
- * This is useful when you are dealing with an object that might or might not be a promise, or if
- * the promise comes from a source that can't be trusted.
- *
- * @param {*} value Value or a promise
- * @returns {Promise} Returns a single promise that will be resolved with an array of values,
- * each value corresponding to the promise at the same index in the `promises` array. If any of
- * the promises is resolved with a rejection, this resulting promise will be resolved with the
- * same rejection.
- */
- var when = function(value, callback, errback) {
- var result = defer(),
- done;
-
- var wrappedCallback = function(value) {
- try {
- return (callback || defaultCallback)(value);
- } catch (e) {
- exceptionHandler(e);
- return reject(e);
- }
- };
-
- var wrappedErrback = function(reason) {
- try {
- return (errback || defaultErrback)(reason);
- } catch (e) {
- exceptionHandler(e);
- return reject(e);
- }
- };
-
- nextTick(function() {
- ref(value).then(function(value) {
- if (done) return;
- done = true;
- result.resolve(ref(value).then(wrappedCallback, wrappedErrback));
- }, function(reason) {
- if (done) return;
- done = true;
- result.resolve(wrappedErrback(reason));
- });
- });
-
- return result.promise;
- };
-
-
- function defaultCallback(value) {
- return value;
- }
-
-
- function defaultErrback(reason) {
- return reject(reason);
- }
-
-
- /**
- * @ngdoc
- * @name ng.$q#all
- * @methodOf ng.$q
- * @description
- * Combines multiple promises into a single promise that is resolved when all of the input
- * promises are resolved.
- *
- * @param {Array.} promises An array of promises.
- * @returns {Promise} Returns a single promise that will be resolved with an array of values,
- * each value corresponding to the promise at the same index in the `promises` array. If any of
- * the promises is resolved with a rejection, this resulting promise will be resolved with the
- * same rejection.
- */
- function all(promises) {
- var deferred = defer(),
- counter = promises.length,
- results = [];
-
- if (counter) {
- forEach(promises, function(promise, index) {
- ref(promise).then(function(value) {
- if (index in results) return;
- results[index] = value;
- if (!(--counter)) deferred.resolve(results);
- }, function(reason) {
- if (index in results) return;
- deferred.reject(reason);
- });
- });
- } else {
- deferred.resolve(results);
- }
-
- return deferred.promise;
- }
-
- return {
- defer: defer,
- reject: reject,
- when: when,
- all: all
- };
-}
-
-/**
- * @ngdoc object
- * @name ng.$routeProvider
- * @function
- *
- * @description
- *
- * Used for configuring routes. See {@link ng.$route $route} for an example.
- */
-function $RouteProvider(){
- var routes = {};
-
- /**
- * @ngdoc method
- * @name ng.$routeProvider#when
- * @methodOf ng.$routeProvider
- *
- * @param {string} path Route path (matched against `$location.path`). If `$location.path`
- * contains redundant trailing slash or is missing one, the route will still match and the
- * `$location.path` will be updated to add or drop the trailing slash to exactly match the
- * route definition.
- *
- * `path` can contain named groups starting with a colon (`:name`). All characters up to the
- * next slash are matched and stored in `$routeParams` under the given `name` when the route
- * matches.
- *
- * @param {Object} route Mapping information to be assigned to `$route.current` on route
- * match.
- *
- * Object properties:
- *
- * - `controller` – `{(string|function()=}` – Controller fn that should be associated with newly
- * created scope or the name of a {@link angular.Module#controller registered controller}
- * if passed as a string.
- * - `template` – `{string=}` – html template as a string that should be used by
- * {@link ng.directive:ngView ngView} or
- * {@link ng.directive:ngInclude ngInclude} directives.
- * this property takes precedence over `templateUrl`.
- * - `templateUrl` – `{string=}` – path to an html template that should be used by
- * {@link ng.directive:ngView ngView}.
- * - `resolve` - `{Object.=}` - An optional map of dependencies which should
- * be injected into the controller. If any of these dependencies are promises, they will be
- * resolved and converted to a value before the controller is instantiated and the
- * `$routeChangeSuccess` event is fired. The map object is:
- *
- * - `key` – `{string}`: a name of a dependency to be injected into the controller.
- * - `factory` - `{string|function}`: If `string` then it is an alias for a service.
- * Otherwise if function, then it is {@link api/AUTO.$injector#invoke injected}
- * and the return value is treated as the dependency. If the result is a promise, it is resolved
- * before its value is injected into the controller.
- *
- * - `redirectTo` – {(string|function())=} – value to update
- * {@link ng.$location $location} path with and trigger route redirection.
- *
- * If `redirectTo` is a function, it will be called with the following parameters:
- *
- * - `{Object.}` - route parameters extracted from the current
- * `$location.path()` by applying the current route templateUrl.
- * - `{string}` - current `$location.path()`
- * - `{Object}` - current `$location.search()`
- *
- * The custom `redirectTo` function is expected to return a string which will be used
- * to update `$location.path()` and `$location.search()`.
- *
- * - `[reloadOnSearch=true]` - {boolean=} - reload route when only $location.search()
- * changes.
- *
- * If the option is set to `false` and url in the browser changes, then
- * `$routeUpdate` event is broadcasted on the root scope.
- *
- * @returns {Object} self
- *
- * @description
- * Adds a new route definition to the `$route` service.
- */
- this.when = function(path, route) {
- routes[path] = extend({reloadOnSearch: true}, route);
-
- // create redirection for trailing slashes
- if (path) {
- var redirectPath = (path[path.length-1] == '/')
- ? path.substr(0, path.length-1)
- : path +'/';
-
- routes[redirectPath] = {redirectTo: path};
- }
-
- return this;
- };
-
- /**
- * @ngdoc method
- * @name ng.$routeProvider#otherwise
- * @methodOf ng.$routeProvider
- *
- * @description
- * Sets route definition that will be used on route change when no other route definition
- * is matched.
- *
- * @param {Object} params Mapping information to be assigned to `$route.current`.
- * @returns {Object} self
- */
- this.otherwise = function(params) {
- this.when(null, params);
- return this;
- };
-
-
- this.$get = ['$rootScope', '$location', '$routeParams', '$q', '$injector', '$http', '$templateCache',
- function( $rootScope, $location, $routeParams, $q, $injector, $http, $templateCache) {
-
- /**
- * @ngdoc object
- * @name ng.$route
- * @requires $location
- * @requires $routeParams
- *
- * @property {Object} current Reference to the current route definition.
- * The route definition contains:
- *
- * - `controller`: The controller constructor as define in route definition.
- * - `locals`: A map of locals which is used by {@link ng.$controller $controller} service for
- * controller instantiation. The `locals` contain
- * the resolved values of the `resolve` map. Additionally the `locals` also contain:
- *
- * - `$scope` - The current route scope.
- * - `$template` - The current route template HTML.
- *
- * @property {Array.