Showing preview only (887K chars total). Download the full file or copy to clipboard to get everything.
Repository: sparkalow/angular-truncate
Branch: master
Commit: 997d4b4bda5d
Files: 16
Total size: 863.6 KB
Directory structure:
gitextract_8gwsmllf/
├── .gitattributes
├── .gitignore
├── Gruntfile.js
├── LICENSE
├── README.md
├── bower.json
├── demo/
│ ├── index.html
│ └── js/
│ └── app.js
├── package.json
├── scripts/
│ └── test.bat
├── src/
│ └── truncate.js
└── test/
├── karma.conf.js
├── lib/
│ └── angular/
│ ├── angular-mocks.js
│ ├── angular-scenario.js
│ └── version.txt
└── unit/
└── filtersSpec.js
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitattributes
================================================
# Auto detect text files and perform LF normalization
* text=auto
# Custom for Visual Studio
*.cs diff=csharp
*.sln merge=union
*.csproj merge=union
*.vbproj merge=union
*.fsproj merge=union
*.dbproj merge=union
# Standard to msysgit
*.doc diff=astextplain
*.DOC diff=astextplain
*.docx diff=astextplain
*.DOCX diff=astextplain
*.dot diff=astextplain
*.DOT diff=astextplain
*.pdf diff=astextplain
*.PDF diff=astextplain
*.rtf diff=astextplain
*.RTF diff=astextplain
================================================
FILE: .gitignore
================================================
*.DS_Store
dist
node_modules
bower_components
.idea
================================================
FILE: Gruntfile.js
================================================
/* global require, module, process */
'use strict';
module.exports = function(grunt) {
// Project configuration.
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
meta: {
banner: '/**\n' +
' * <%= pkg.description %>\n' +
' * @version v<%= pkg.version %> - <%= grunt.template.today("yyyy-mm-dd") %>\n' +
' * @link <%= pkg.homepage %>\n' +
' * @author <%= pkg.author %>\n' +
' * @license MIT License, http://www.opensource.org/licenses/MIT\n' +
' */\n'
},
dirs: {
dest: 'dist'
},
concat: {
options: {
banner: '<%= meta.banner %>'
},
dist: {
src: ['src/*.js'],
dest: '<%= dirs.dest %>/<%= pkg.name %>.js'
}
},
uglify: {
options: {
banner: '<%= meta.banner %>'
},
dist: {
src: ['<%= concat.dist.dest %>'],
dest: '<%= dirs.dest %>/<%= pkg.name %>.min.js'
}
},
jshint: {
files: ['Gruntfile.js', 'src/*.js', 'test/unit/*.js'],
options: {
curly: false,
browser: true,
eqeqeq: true,
immed: true,
latedef: true,
newcap: true,
noarg: true,
sub: true,
undef: true,
boss: true,
eqnull: true,
expr: true,
node: true,
globals: {
exports: true,
angular: false,
$: false
}
}
},
// watch: {
// files: '<config:jshint.files>',
// tasks: 'default'
// },
karma: {
test: {
options: {
reporters: ['dots'],
singleRun: true
}
},
options: {
configFile: 'test/karma.conf.js'
}
}
});
// Load the plugin that provides the "jshint" task.
grunt.loadNpmTasks('grunt-contrib-jshint');
// Load the plugin that provides the "concat" task.
grunt.loadNpmTasks('grunt-contrib-concat');
// Load the plugin that provides the "uglify" task.
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.loadNpmTasks('grunt-contrib-connect');
// Load the plugin that provides the "watch" task.
//grunt.loadNpmTasks('grunt-contrib-watch');
// Default task.
grunt.registerTask('default', ['test']);
// Test tasks.
grunt.registerTask('test', ['jshint', 'karma:test']);
grunt.registerTask('test-server', ['karma:server']);
// Build task.
grunt.registerTask('build', ['test', 'concat', 'uglify']);
// run devserver
grunt.registerTask('webserver', ['connect:devserver']);
// Provides the "karma" task.
grunt.registerMultiTask('karma', 'Starts up a karma server.', function() {
var done = this.async();
require('karma').server.start(this.options(), function(code) {
done(code === 0);
});
});
};
================================================
FILE: LICENSE
================================================
The MIT License
Copyright (c) 2013 Brian Matthews
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
================================================
FILE: README.md
================================================
Angular Truncate
---------
This project is a filter for Angularjs to truncate text strings to a set number of characters or words and
add ellipses when needed.
[Demo](http://sparkalow.github.io/angular-truncate/)
## How to use angular truncate
###Include the javascript file.
``` html
<script src="truncate.js"></script>
```
###Inject the `truncate` filter into your app module.
```javascript
var myApp = angular.module('myApp', ['truncate']);
```
###When outputting text, apply the filter.
```html
<p>
{{ text | characters:25 }} or {{ text | words:5 }}
</p>
```
By default, a _word_ will not be truncated. Set the optional boolean after the character count to true.
```html
<p>
{{ text | characters:25 :true}}
</p>
```
================================================
FILE: bower.json
================================================
{
"name": "angular-truncate",
"version": "0.1.2",
"main": ["./src/truncate.js"],
"dependencies": {
"angular": "~1.2.0"
}
}
================================================
FILE: demo/index.html
================================================
<!DOCTYPE html>
<html ng-app="myApp">
<head>
<link href="http://netdna.bootstrapcdn.com/twitter-bootstrap/2.3.1/css/bootstrap-combined.min.css" rel="stylesheet">
<title>Angular truncate text filter demo</title>
<script src="../test/lib/angular/angular.min.js"></script>
<script src="../src/truncate.js"></script>
<script src="js/app.js"></script>
</head>
<body ng-controller="demoController">
<div class="container">
<h2>Angular Truncate Demo</h2>
<div class="hero-unit">
<h4>Example Text</h4>
<textarea ng-model="text" rows="3" placeholder="Enter test text"></textarea>
<br><br>
<strong>Truncate by characters</strong>
<label>Number of characters (will not break on a word):
<input ng-model="numChars" type="number"/></label>
<label>Break in the middle of words <input type="checkbox" ng-model="breakOnWord"/></label>
<h4>Output</h4>
<div class="well text-info">
<p>
{{ text | characters:numChars : breakOnWord }}
</p>
</div>
<h4>Code</h4>
<pre>{<span></span>{ text | characters:{{ numChars }}: {{ breakOnWord }}<span></span>}</pre>
</div>
<div class="hero-unit">
<strong>Truncate by words</strong>
<label>Number of words:
<input ng-model="numWords" type="number"/>
</label>
<h4>Code</h4>
<pre>{<span></span>{ text | words:{{ numWords }}:ignoreSpaces }<span></span>}</pre>
<h4>Output</h4>
<div class="well text-info">
<p>
{{ text | words:numWords }}
</p>
</div>
</div>
<br><br>
<hr/>
<p>
<a href="https://raw.github.com/sparkalow/angular-infinite-scroll/master/src/infinite-scroll.js" class="btn btn-primary">Download</a><span class="help-inline">infinite-scroll.js</span>
</p>
</div>
</body>
</html>
================================================
FILE: demo/js/app.js
================================================
// Declare app level module which depends on filters, and services
var myApp = angular.module('myApp', ['truncate']);
myApp.controller('demoController', function ($scope) {
$scope.text = 'Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.';
$scope.numChars = 20;
$scope.numWords = 5;
$scope.breakOnWord = false;
});
================================================
FILE: package.json
================================================
{
"name": "angular-truncate",
"description": "Angular Truncate - Ellipsis for your templates",
"version": "0.1.2",
"homepage": "http://sparkalow.github.com/angular-truncate",
"author": "Brian Mathews (sparkalow)",
"main" : "src/truncate.js",
"repository": {
"type": "git",
"url": "git://github.com/sparkalow/angular-truncate.git"
},
"engines": {
"node": ">= 0.8"
},
"licenses": [
{
"type": "MIT",
"url": "http://mit-license.org"
}
],
"dependencies": {},
"devDependencies": {
"grunt": ">= 0.4.0",
"grunt-contrib-concat": "^0.5.0",
"grunt-contrib-jshint": "^0.10.0",
"grunt-contrib-uglify": "*",
"karma": "~ 0.8.0"
},
"scripts": {
"test": "karma start test/karma.conf.js --single-run --browsers Chrome",
"test-server": "karma start test/karma.conf.js --browsers Chrome"
}
}
================================================
FILE: scripts/test.bat
================================================
echo off
REM Windows script for running unit tests
REM You have to run server and capture some browser first
REM
REM Requirements:
REM - NodeJS (http://nodejs.org/)
REM - Karma (npm install -g karma)
set BASE_DIR=%~dp0
karma start "%BASE_DIR%\..\test\karma.conf.js" %*
================================================
FILE: src/truncate.js
================================================
angular.module('truncate', [])
.filter('characters', function () {
return function (input, chars, breakOnWord) {
if (isNaN(chars)) return input;
if (chars <= 0) return '';
if (input && input.length > chars) {
input = input.substring(0, chars);
if (!breakOnWord) {
var lastspace = input.lastIndexOf(' ');
//get last space
if (lastspace !== -1) {
input = input.substr(0, lastspace);
}
}else{
while(input.charAt(input.length-1) === ' '){
input = input.substr(0, input.length -1);
}
}
return input + '…';
}
return input;
};
})
.filter('splitcharacters', function() {
return function (input, chars) {
if (isNaN(chars)) return input;
if (chars <= 0) return '';
if (input && input.length > chars) {
var prefix = input.substring(0, chars/2);
var postfix = input.substring(input.length-chars/2, input.length);
return prefix + '...' + postfix;
}
return input;
};
})
.filter('words', function () {
return function (input, words) {
if (isNaN(words)) return input;
if (words <= 0) return '';
if (input) {
var inputWords = input.split(/\s+/);
if (inputWords.length > words) {
input = inputWords.slice(0, words).join(' ') + '…';
}
}
return input;
};
});
================================================
FILE: test/karma.conf.js
================================================
// Testacular configuration file
//
// For all available config options and default values, see:
// https://github.com/vojtajina/testacular/blob/stable/lib/config.js#L54
// base path, that will be used to resolve files and exclude
basePath = './..';
// frameworks to use
// frameworks = ['jasmine'];
// list of files / patterns to load in the browser
files = [
JASMINE,
JASMINE_ADAPTER,
'test/lib/angular/angular.min.js',
'test/lib/angular/angular-mocks.js',
'src/*.js',
'test/unit/*.js'
];
// list of files to exclude
exclude = [];
// use dots reporter, as travis terminal does not support escaping sequences
// possible values: 'dots', 'progress', 'junit'
// CLI --reporters progress
// 'coverage',
reporters = ['progress'];
// web server port
// CLI --port 9876
port = 9876;
// cli runner port
// CLI --runner-port 9100
runnerPort = 9100;
// enable / disable colors in the output (reporters and logs)
// CLI --colors --no-colors
colors = true;
// level of logging
// possible values: LOG_DISABLE || LOG_ERROR || LOG_WARN || LOG_INFO || LOG_DEBUG
// CLI --log-level debug
logLevel = LOG_INFO;
// enable / disable watching file and executing tests whenever any file changes
// CLI --auto-watch --no-auto-watch
autoWatch = true;
// Start these browsers, currently available:
// - Chrome
// - ChromeCanary
// - Firefox
// - Opera
// - Safari (only Mac)
// - PhantomJS
// - IE (only Windows)
// CLI --browsers Chrome,Firefox,Safari
browsers = ['Chrome'];
// If browser does not capture in given timeout [ms], kill it
// CLI --capture-timeout 5000
captureTimeout = 5000;
// Auto run tests on start (when browsers are captured) and exit
// CLI --single-run --no-single-run
singleRun = false;
// report which specs are slower than 500ms
// CLI --report-slower-than 500
reportSlowerThan = 500;
================================================
FILE: test/lib/angular/angular-mocks.js
================================================
/**
* @license AngularJS v1.0.6
* (c) 2010-2012 Google, Inc. http://angularjs.org
* License: MIT
*
* TODO(vojta): wrap whole file into closure during build
*/
/**
* @ngdoc overview
* @name angular.mock
* @description
*
* Namespace from 'angular-mocks.js' which contains testing related code.
*/
angular.mock = {};
/**
* ! This is a private undocumented service !
*
* @name ngMock.$browser
*
* @description
* This service is a mock implementation of {@link ng.$browser}. It provides fake
* implementation for commonly used browser apis that are hard to test, e.g. setTimeout, xhr,
* cookies, etc...
*
* The api of this service is the same as that of the real {@link ng.$browser $browser}, except
* that there are several helper methods available which can be used in tests.
*/
angular.mock.$BrowserProvider = function() {
this.$get = function(){
return new angular.mock.$Browser();
};
};
angular.mock.$Browser = function() {
var self = this;
this.isMock = true;
self.$$url = "http://server/";
self.$$lastUrl = self.$$url; // used by url polling fn
self.pollFns = [];
// TODO(vojta): remove this temporary api
self.$$completeOutstandingRequest = angular.noop;
self.$$incOutstandingRequestCount = angular.noop;
// register url polling fn
self.onUrlChange = function(listener) {
self.pollFns.push(
function() {
if (self.$$lastUrl != self.$$url) {
self.$$lastUrl = self.$$url;
listener(self.$$url);
}
}
);
return listener;
};
self.cookieHash = {};
self.lastCookieHash = {};
self.deferredFns = [];
self.deferredNextId = 0;
self.defer = function(fn, delay) {
delay = delay || 0;
self.deferredFns.push({time:(self.defer.now + delay), fn:fn, id: self.deferredNextId});
self.deferredFns.sort(function(a,b){ return a.time - b.time;});
return self.deferredNextId++;
};
self.defer.now = 0;
self.defer.cancel = function(deferId) {
var fnIndex;
angular.forEach(self.deferredFns, function(fn, index) {
if (fn.id === deferId) fnIndex = index;
});
if (fnIndex !== undefined) {
self.deferredFns.splice(fnIndex, 1);
return true;
}
return false;
};
/**
* @name ngMock.$browser#defer.flush
* @methodOf ngMock.$browser
*
* @description
* Flushes all pending requests and executes the defer callbacks.
*
* @param {number=} number of milliseconds to flush. See {@link #defer.now}
*/
self.defer.flush = function(delay) {
if (angular.isDefined(delay)) {
self.defer.now += delay;
} else {
if (self.deferredFns.length) {
self.defer.now = self.deferredFns[self.deferredFns.length-1].time;
} else {
throw Error('No deferred tasks to be flushed');
}
}
while (self.deferredFns.length && self.deferredFns[0].time <= self.defer.now) {
self.deferredFns.shift().fn();
}
};
/**
* @name ngMock.$browser#defer.now
* @propertyOf ngMock.$browser
*
* @description
* Current milliseconds mock time.
*/
self.$$baseHref = '';
self.baseHref = function() {
return this.$$baseHref;
};
};
angular.mock.$Browser.prototype = {
/**
* @name ngMock.$browser#poll
* @methodOf ngMock.$browser
*
* @description
* run all fns in pollFns
*/
poll: function poll() {
angular.forEach(this.pollFns, function(pollFn){
pollFn();
});
},
addPollFn: function(pollFn) {
this.pollFns.push(pollFn);
return pollFn;
},
url: function(url, replace) {
if (url) {
this.$$url = url;
return this;
}
return this.$$url;
},
cookies: function(name, value) {
if (name) {
if (value == undefined) {
delete this.cookieHash[name];
} else {
if (angular.isString(value) && //strings only
value.length <= 4096) { //strict cookie storage limits
this.cookieHash[name] = value;
}
}
} else {
if (!angular.equals(this.cookieHash, this.lastCookieHash)) {
this.lastCookieHash = angular.copy(this.cookieHash);
this.cookieHash = angular.copy(this.cookieHash);
}
return this.cookieHash;
}
},
notifyWhenNoOutstandingRequests: function(fn) {
fn();
}
};
/**
* @ngdoc object
* @name ngMock.$exceptionHandlerProvider
*
* @description
* Configures the mock implementation of {@link ng.$exceptionHandler} to rethrow or to log errors passed
* into the `$exceptionHandler`.
*/
/**
* @ngdoc object
* @name ngMock.$exceptionHandler
*
* @description
* Mock implementation of {@link ng.$exceptionHandler} that rethrows or logs errors passed
* into it. See {@link ngMock.$exceptionHandlerProvider $exceptionHandlerProvider} for configuration
* information.
*
*
* <pre>
* describe('$exceptionHandlerProvider', function() {
*
* it('should capture log messages and exceptions', function() {
*
* module(function($exceptionHandlerProvider) {
* $exceptionHandlerProvider.mode('log');
* });
*
* inject(function($log, $exceptionHandler, $timeout) {
* $timeout(function() { $log.log(1); });
* $timeout(function() { $log.log(2); throw 'banana peel'; });
* $timeout(function() { $log.log(3); });
* expect($exceptionHandler.errors).toEqual([]);
* expect($log.assertEmpty());
* $timeout.flush();
* expect($exceptionHandler.errors).toEqual(['banana peel']);
* expect($log.log.logs).toEqual([[1], [2], [3]]);
* });
* });
* });
* </pre>
*/
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".
*
* <pre>
* var newYearInBratislava = new TzDate(-1, '2009-12-31T23:00:00Z');
* newYearInBratislava.getTimezoneOffset() => -60;
* newYearInBratislava.getFullYear() => 2010;
* newYearInBratislava.getMonth() => 0;
* newYearInBratislava.getDate() => 1;
* newYearInBratislava.getHours() => 0;
* newYearInBratislava.getMinutes() => 0;
* </pre>
*
*/
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('<div></div>');
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.
*
*
* <table class="table">
* <tr><th width="220px"></th><th>Request expectations</th><th>Backend definitions</th></tr>
* <tr>
* <th>Syntax</th>
* <td>.expect(...).respond(...)</td>
* <td>.when(...).respond(...)</td>
* </tr>
* <tr>
* <th>Typical usage</th>
* <td>strict unit tests</td>
* <td>loose (black-box) unit testing</td>
* </tr>
* <tr>
* <th>Fulfills multiple requests</th>
* <td>NO</td>
* <td>YES</td>
* </tr>
* <tr>
* <th>Order of requests matters</th>
* <td>YES</td>
* <td>NO</td>
* </tr>
* <tr>
* <th>Request required</th>
* <td>YES</td>
* <td>NO</td>
* </tr>
* <tr>
* <th>Response required</th>
* <td>optional (see below)</td>
* <td>YES</td>
* </tr>
* </table>
*
* 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
*
* <pre>
// 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();
});
</pre>
*/
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.
*
* <pre>
* afterEach($httpBackend.verifyExpectations);
* </pre>
*/
$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.
*
* <pre>
* afterEach($httpBackend.verifyNoOutstandingRequest);
* </pre>
*/
$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('<div ng-app></div>');
}
};
/**
* @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:
*
* <pre>
* 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();
* //...
* });
* </pre>
*
* 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.<br>
* *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.<br>
* *NOTE*: Only available with {@link http://pivotal.github.com/jasmine/ jasmine}.
=======
* *NOTE*: This function is also published on window for easy access.<br>
>>>>>>> 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.
* <pre>
*
* 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');
* });
* ));
* });
*
* </pre>
*
* @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);
================================================
FILE: test/lib/angular/angular-scenario.js
================================================
/*!
* 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 <tag> 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 = " <link/><table></table><a href='/a' style='top:1px;float:left;opacity:.55;'>a</a><input type='checkbox'/>";
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></: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 = "<div " + style + "display:block;'><div style='" + paddingMarginBorder + "0;display:block;overflow:hidden;'></div></div>" +
"<table " + style + "' cellpadding='0' cellspacing='0'>" +
"<tr><td></td></tr></table>";
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 = "<table><tr><td style='" + paddingMarginBorder + "0;display:none'></td><td>t</td></tr></table>";
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 = "<div style='width:5px;'></div>";
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: func
gitextract_8gwsmllf/
├── .gitattributes
├── .gitignore
├── Gruntfile.js
├── LICENSE
├── README.md
├── bower.json
├── demo/
│ ├── index.html
│ └── js/
│ └── app.js
├── package.json
├── scripts/
│ └── test.bat
├── src/
│ └── truncate.js
└── test/
├── karma.conf.js
├── lib/
│ └── angular/
│ ├── angular-mocks.js
│ ├── angular-scenario.js
│ └── version.txt
└── unit/
└── filtersSpec.js
SYMBOL INDEX (226 symbols across 2 files)
FILE: test/lib/angular/angular-mocks.js
function concat (line 297) | function concat(array1, array2, index) {
function jsonStringToDate (line 391) | function jsonStringToDate(string){
function int (line 408) | function int(str) {
function padNumber (line 412) | function padNumber(num, digits, trim) {
function serialize (line 603) | function serialize(object) {
function serializeScope (line 634) | function serializeScope(scope, offset) {
function createHttpBackendMock (line 841) | function createHttpBackendMock($delegate, $browser) {
function MockHttpExpectation (line 1262) | function MockHttpExpectation(method, url, data, headers) {
function MockXhr (line 1299) | function MockXhr() {
function getCurrentSpec (line 1642) | function getCurrentSpec() {
function isSpecRunning (line 1646) | function isSpecRunning() {
function workFn (line 1672) | function workFn() {
function workFn (line 1747) | function workFn() {
FILE: test/lib/angular/angular-scenario.js
function jQuerySub (line 898) | function jQuerySub( selector, context ) {
function doScrollCheck (line 964) | function doScrollCheck() {
function createFlags (line 991) | function createFlags( flags ) {
function resolveFunc (line 1326) | function resolveFunc( i ) {
function progressFunc (line 1334) | function progressFunc( i ) {
function dataAttr (line 1986) | function dataAttr( elem, key, data ) {
function isEmptyDataObject (line 2017) | function isEmptyDataObject( obj ) {
function handleQueueMarkDefer (line 2035) | function handleQueueMarkDefer( elem, type, src ) {
function resolve (line 2194) | function resolve() {
function returnFalse (line 3547) | function returnFalse() {
function returnTrue (line 3550) | function returnTrue() {
function dirNodeCheck (line 5261) | function dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {
function dirCheck (line 5294) | function dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {
function isDisconnected (line 5567) | function isDisconnected( node ) {
function winnow (line 5684) | function winnow( elements, qualifier, keep ) {
function createSafeFragment (line 5721) | function createSafeFragment( document ) {
function root (line 6093) | function root( elem, cur ) {
function cloneCopyEvent (line 6100) | function cloneCopyEvent( src, dest ) {
function cloneFixAttributes (line 6128) | function cloneFixAttributes( src, dest ) {
function getAll (line 6273) | function getAll( elem ) {
function fixDefaultChecked (line 6286) | function fixDefaultChecked( elem ) {
function findInputs (line 6292) | function findInputs( elem ) {
function shimCloneNode (line 6303) | function shimCloneNode( elem ) {
function getWidthOrHeight (line 6794) | function getWidthOrHeight( elem, name, extra ) {
function addToPrefiltersOrTransports (line 7035) | function addToPrefiltersOrTransports( structure ) {
function inspectPrefiltersOrTransports (line 7071) | function inspectPrefiltersOrTransports( structure, options, originalOpti...
function ajaxExtend (line 7113) | function ajaxExtend( target, src ) {
function done (line 7455) | function done( status, nativeStatusText, responses, headers ) {
function buildParams (line 7770) | function buildParams( prefix, obj, traditional, add ) {
function ajaxHandleResponses (line 7820) | function ajaxHandleResponses( s, jqXHR, responses ) {
function ajaxConvert (line 7885) | function ajaxConvert( s, response ) {
function createStandardXHR (line 8150) | function createStandardXHR() {
function createActiveXHR (line 8156) | function createActiveXHR() {
function doAnimation (line 8495) | function doAnimation() {
function stopQueue (line 8651) | function stopQueue( elem, data, index ) {
function createFxNow (line 8693) | function createFxNow() {
function clearFxNow (line 8698) | function clearFxNow() {
function genFx (line 8703) | function genFx( type, num ) {
function t (line 8818) | function t( gotoEnd ) {
function defaultDisplay (line 9016) | function defaultDisplay( nodeName ) {
function getWindow (line 9300) | function getWindow( elem ) {
function isArrayLike (line 9510) | function isArrayLike(obj) {
function forEach (line 9527) | function forEach(obj, iterator, context) {
function sortedKeys (line 9552) | function sortedKeys(obj) {
function forEachSorted (line 9562) | function forEachSorted(obj, iterator, context) {
function reverseParams (line 9576) | function reverseParams(iteratorFn) {
function nextUid (line 9588) | function nextUid() {
function extend (line 9622) | function extend(dst) {
function int (line 9633) | function int(str) {
function inherit (line 9638) | function inherit(parent, extra) {
function noop (line 9658) | function noop() {}
function identity (line 9677) | function identity($) {return $;}
function valueFn (line 9681) | function valueFn(value) {return function() {return value;};}
function isUndefined (line 9694) | function isUndefined(value){return typeof value == 'undefined';}
function isDefined (line 9708) | function isDefined(value){return typeof value != 'undefined';}
function isObject (line 9723) | function isObject(value){return value != null && typeof value == 'object';}
function isString (line 9737) | function isString(value){return typeof value == 'string';}
function isNumber (line 9751) | function isNumber(value){return typeof value == 'number';}
function isDate (line 9765) | function isDate(value){
function isArray (line 9781) | function isArray(value) {
function isFunction (line 9797) | function isFunction(value){return typeof value == 'function';}
function isWindow (line 9807) | function isWindow(obj) {
function isScope (line 9812) | function isScope(obj) {
function isFile (line 9817) | function isFile(obj) {
function isBoolean (line 9822) | function isBoolean(value) {
function trim (line 9827) | function trim(value) {
function isElement (line 9842) | function isElement(node) {
function makeMap (line 9852) | function makeMap(str){
function map (line 9873) | function map(obj, iterator, context) {
function size (line 9894) | function size(obj, ownPropsOnly) {
function includes (line 9909) | function includes(array, obj) {
function indexOf (line 9913) | function indexOf(array, obj) {
function arrayRemove (line 9922) | function arrayRemove(array, value) {
function isLeafNode (line 9929) | function isLeafNode (node) {
function copy (line 9963) | function copy(source, destination){
function shallowCopy (line 9998) | function shallowCopy(src, dst) {
function equals (line 10035) | function equals(o1, o2) {
function concat (line 10073) | function concat(array1, array2, index) {
function sliceArgs (line 10077) | function sliceArgs(args, startIndex) {
function bind (line 10097) | function bind(self, fn) {
function toJsonReplacer (line 10118) | function toJsonReplacer(key, value) {
function toJson (line 10147) | function toJson(obj, pretty) {
function fromJson (line 10163) | function fromJson(json) {
function toBoolean (line 10170) | function toBoolean(value) {
function startingTag (line 10183) | function startingTag(element) {
function parseKeyValue (line 10211) | function parseKeyValue(/**string*/keyValue) {
function toKeyValue (line 10223) | function toKeyValue(obj) {
function encodeUriSegment (line 10243) | function encodeUriSegment(val) {
function encodeUriQuery (line 10262) | function encodeUriQuery(val, pctEncodeSpaces) {
function angularInit (line 10300) | function angularInit(element, bootstrap) {
function bootstrap (line 10356) | function bootstrap(element, modules) {
function snake_case (line 10392) | function snake_case(name, separator){
function bindJQuery (line 10399) | function bindJQuery() {
function assertArg (line 10423) | function assertArg(arg, name, reason) {
function assertArgFn (line 10430) | function assertArgFn(arg, name, acceptArrayAnnotation) {
function setupModuleLoader (line 10448) | function setupModuleLoader(window) {
function publishExternalAPI (line 10710) | function publishExternalAPI(angular){
function jqNextId (line 10904) | function jqNextId() { return ++jqId; }
function camelCase (line 10915) | function camelCase(name) {
function JQLitePatchJQueryRemove (line 10931) | function JQLitePatchJQueryRemove(name, dispatchThis) {
function JQLite (line 10965) | function JQLite(element) {
function JQLiteClone (line 10989) | function JQLiteClone(element) {
function JQLiteDealoc (line 10993) | function JQLiteDealoc(element){
function JQLiteUnbind (line 11000) | function JQLiteUnbind(element, type, fn) {
function JQLiteRemoveData (line 11021) | function JQLiteRemoveData(element) {
function JQLiteExpandoStore (line 11035) | function JQLiteExpandoStore(element, key, value) {
function JQLiteData (line 11050) | function JQLiteData(element, key, value) {
function JQLiteHasClass (line 11076) | function JQLiteHasClass(element, selector) {
function JQLiteRemoveClass (line 11081) | function JQLiteRemoveClass(element, cssClasses) {
function JQLiteAddClass (line 11093) | function JQLiteAddClass(element, cssClasses) {
function JQLiteAddNodes (line 11103) | function JQLiteAddNodes(root, elements) {
function JQLiteController (line 11114) | function JQLiteController(element, name) {
function JQLiteInheritedData (line 11118) | function JQLiteInheritedData(element, name, value) {
function trigger (line 11140) | function trigger() {
function getBooleanAttrName (line 11180) | function getBooleanAttrName(element, name) {
function createEventHandler (line 11346) | function createEventHandler(element, events) {
function hashKey (line 11594) | function hashKey(obj) {
function HashMap (line 11615) | function HashMap(array){
function HashQueueMap (line 11651) | function HashQueueMap() {}
function annotate (line 11733) | function annotate(fn) {
function createInjector (line 12086) | function createInjector(modulesToLoad) {
function $AnchorScrollProvider (line 12309) | function $AnchorScrollProvider() {
function Browser (line 12383) | function Browser(window, document, $log, $sniffer) {
function $BrowserProvider (line 12716) | function $BrowserProvider(){
function $CacheFactoryProvider (line 12746) | function $CacheFactoryProvider() {
function $TemplateCacheProvider (line 12888) | function $TemplateCacheProvider() {
function $CompileProvider (line 13044) | function $CompileProvider($provide) {
function directiveNormalize (line 14037) | function directiveNormalize(name) {
function nodesetLinkingFn (line 14084) | function nodesetLinkingFn(
function directiveLinkingFn (line 14091) | function directiveLinkingFn(
function $ControllerProvider (line 14109) | function $ControllerProvider() {
function $DocumentProvider (line 14179) | function $DocumentProvider(){
function $ExceptionHandlerProvider (line 14203) | function $ExceptionHandlerProvider() {
function $InterpolateProvider (line 14220) | function $InterpolateProvider() {
function encodePath (line 14404) | function encodePath(path) {
function stripHash (line 14415) | function stripHash(url) {
function matchUrl (line 14420) | function matchUrl(url, obj) {
function composeProtocolHostPort (line 14442) | function composeProtocolHostPort(protocol, host, port) {
function pathPrefixFromBase (line 14447) | function pathPrefixFromBase(basePath) {
function convertToHtml5Url (line 14452) | function convertToHtml5Url(url, basePath, hashPrefix) {
function convertToHashbangUrl (line 14467) | function convertToHashbangUrl(url, basePath, hashPrefix) {
function LocationUrl (line 14499) | function LocationUrl(url, pathPrefix, appBaseUrl) {
function LocationHashbangUrl (line 14554) | function LocationHashbangUrl(url, hashPrefix, appBaseUrl) {
function LocationHashbangInHtml5Url (line 14792) | function LocationHashbangInHtml5Url(url, hashPrefix, appBaseUrl, baseExt...
function locationGetter (line 14805) | function locationGetter(property) {
function locationGetterSetter (line 14812) | function locationGetterSetter(property, preprocess) {
function $LocationProvider (line 14860) | function $LocationProvider(){
function $LogProvider (line 15043) | function $LogProvider(){
function lex (line 15158) | function lex(text, csp){
function parser (line 15392) | function parser(text, json, $filter, csp){
function setter (line 15772) | function setter(obj, path, setValue) {
function getter (line 15795) | function getter(obj, path, bindFnToScope) {
function cspSafeGetterFn (line 15821) | function cspSafeGetterFn(key0, key1, key2, key3, key4) {
function getterFn (line 15885) | function getterFn(path, csp) {
function $ParseProvider (line 15972) | function $ParseProvider() {
function $QProvider (line 16138) | function $QProvider() {
function qFactory (line 16156) | function qFactory(nextTick, exceptionHandler) {
function $RouteProvider (line 16413) | function $RouteProvider(){
function $RouteParamsProvider (line 16898) | function $RouteParamsProvider() {
function $RootScopeProvider (line 16960) | function $RootScopeProvider(){
function $SnifferProvider (line 17730) | function $SnifferProvider() {
function $WindowProvider (line 17786) | function $WindowProvider(){
function parseHeaders (line 17796) | function parseHeaders(headers) {
function headersGetter (line 17831) | function headersGetter(headers) {
function transformData (line 17856) | function transformData(data, headers, fns) {
function isSuccess (line 17868) | function isSuccess(status) {
function $HttpProvider (line 17873) | function $HttpProvider() {
function $HttpBackendProvider (line 18586) | function $HttpBackendProvider() {
function createHttpBackend (line 18593) | function createHttpBackend($browser, XHR, $browserDefer, callbacks, rawD...
function $LocaleProvider (line 18720) | function $LocaleProvider(){
function $TimeoutProvider (line 18781) | function $TimeoutProvider() {
function $FilterProvider (line 18941) | function $FilterProvider($provide) {
function filterFilter (line 19048) | function filterFilter() {
function currencyFilter (line 19173) | function currencyFilter($locale) {
function numberFilter (line 19230) | function numberFilter($locale) {
function formatNumber (line 19239) | function formatNumber(number, pattern, groupSep, decimalSep, fractionSiz...
function padNumber (line 19308) | function padNumber(num, digits, trim) {
function dateGetter (line 19322) | function dateGetter(name, size, offset, trim) {
function dateStrGetter (line 19332) | function dateStrGetter(name, shortForm) {
function timeZoneGetter (line 19341) | function timeZoneGetter(date) {
function ampmGetter (line 19351) | function ampmGetter(date, formats) {
function dateFilter (line 19463) | function dateFilter($locale) {
function jsonFilter (line 19558) | function jsonFilter() {
function limitToFilter (line 19639) | function limitToFilter(){
function orderByFilter (line 19759) | function orderByFilter($parse){
function ngDirective (line 19808) | function ngDirective(directive) {
function FormController (line 20211) | function FormController(element, attrs) {
function isEmpty (line 20840) | function isEmpty(value) {
function textInputType (line 20845) | function textInputType(scope, element, attr, ctrl, $sniffer, $browser) {
function numberInputType (line 20958) | function numberInputType(scope, element, attr, ctrl, $sniffer, $browser) {
function urlInputType (line 21020) | function urlInputType(scope, element, attr, ctrl, $sniffer, $browser) {
function emailInputType (line 21037) | function emailInputType(scope, element, attr, ctrl, $sniffer, $browser) {
function radioInputType (line 21054) | function radioInputType(scope, element, attr, ctrl) {
function checkboxInputType (line 21076) | function checkboxInputType(scope, element, attr, ctrl) {
function toggleValidCss (line 21381) | function toggleValidCss(isValid, validationErrorKey) {
function classDirective (line 21874) | function classDirective(name, selector) {
function destroyLastScope (line 23493) | function destroyLastScope() {
function clearContent (line 23500) | function clearContent() {
function update (line 23505) | function update() {
function Single (line 23819) | function Single(scope, selectElement, ngModelCtrl, selectCtrl) {
function Multiple (line 23844) | function Multiple(scope, selectElement, ctrl) {
function Options (line 23875) | function Options(scope, selectElement, ctrl) {
function executeStatement (line 24188) | function executeStatement(statement, args) {
function asyncForEach (line 24306) | function asyncForEach(list, iterator, done) {
function formatException (line 24333) | function formatException(error, maxStackLines) {
function callerFile (line 24356) | function callerFile(offset) {
function browserTrigger (line 24386) | function browserTrigger(element, type, keys) {
function push (line 24531) | function push(value) {
function complete (line 25007) | function complete(item) {
function findContext (line 26089) | function findContext(spec) {
function updateTotals (line 26113) | function updateTotals(status) {
function addError (line 26127) | function addError(context, line, error) {
function serializeXml (line 26160) | function serializeXml(context, tree) {
Condensed preview — 16 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (940K chars).
[
{
"path": ".gitattributes",
"chars": 484,
"preview": "# Auto detect text files and perform LF normalization\n* text=auto\n\n# Custom for Visual Studio\n*.cs diff=csharp\n*.sln"
},
{
"path": ".gitignore",
"chars": 52,
"preview": "*.DS_Store\ndist\nnode_modules\nbower_components\n.idea\n"
},
{
"path": "Gruntfile.js",
"chars": 2780,
"preview": "/* global require, module, process */\n\n'use strict';\n\nmodule.exports = function(grunt) {\n\n // Project configuration.\n "
},
{
"path": "LICENSE",
"chars": 1075,
"preview": "The MIT License\nCopyright (c) 2013 Brian Matthews\n\nPermission is hereby granted, free of charge, to any person obtaining"
},
{
"path": "README.md",
"chars": 741,
"preview": "Angular Truncate\n---------\nThis project is a filter for Angularjs to truncate text strings to a set number of characters"
},
{
"path": "bower.json",
"chars": 138,
"preview": "{\n \"name\": \"angular-truncate\",\n \"version\": \"0.1.2\",\n \"main\": [\"./src/truncate.js\"],\n \"dependencies\": {\n \"angular\""
},
{
"path": "demo/index.html",
"chars": 1926,
"preview": "<!DOCTYPE html>\n<html ng-app=\"myApp\">\n<head>\n <link href=\"http://netdna.bootstrapcdn.com/twitter-bootstrap/2.3.1/css/"
},
{
"path": "demo/js/app.js",
"chars": 619,
"preview": "// Declare app level module which depends on filters, and services\nvar myApp = angular.module('myApp', ['truncate']);\n\n\n"
},
{
"path": "package.json",
"chars": 869,
"preview": "{\n \"name\": \"angular-truncate\",\n \"description\": \"Angular Truncate - Ellipsis for your templates\",\n \"version\": \"0.1.2\","
},
{
"path": "scripts/test.bat",
"chars": 271,
"preview": "echo off\n\nREM Windows script for running unit tests\nREM You have to run server and capture some browser first\nREM\nREM Re"
},
{
"path": "src/truncate.js",
"chars": 1756,
"preview": "angular.module('truncate', [])\n .filter('characters', function () {\n return function (input, chars, breakOnWor"
},
{
"path": "test/karma.conf.js",
"chars": 1814,
"preview": "// Testacular configuration file\n//\n// For all available config options and default values, see:\n// https://github.com/v"
},
{
"path": "test/lib/angular/angular-mocks.js",
"chars": 60277,
"preview": "/**\n * @license AngularJS v1.0.6\n * (c) 2010-2012 Google, Inc. http://angularjs.org\n * License: MIT\n *\n * TODO(vojta): w"
},
{
"path": "test/lib/angular/angular-scenario.js",
"chars": 806864,
"preview": "/*!\n * jQuery JavaScript Library v1.7.2\n * http://jquery.com/\n *\n * Copyright 2011, John Resig\n * Dual licensed under th"
},
{
"path": "test/lib/angular/version.txt",
"chars": 1,
"preview": "\n"
},
{
"path": "test/unit/filtersSpec.js",
"chars": 4655,
"preview": "/*global module, inject, beforeEach, expect, describe, it */\n\n'use strict';\n\ndescribe('truncate', function () {\n\n bef"
}
]
About this extraction
This page contains the full source code of the sparkalow/angular-truncate GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 16 files (863.6 KB), approximately 224.0k tokens, and a symbol index with 226 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.