├── .gitignore ├── spec ├── SpecHelper.js ├── WriteSpec.js └── ReadSpec.js ├── images ├── step-1-1.png ├── step-1-2.png ├── step-1-3.png ├── step-2-1.png ├── step-2-2.png ├── step-3-1.png ├── step-3-2.png └── step-3-3.png ├── lib └── jasmine-2.4.1 │ ├── jasmine_favicon.png │ ├── boot.js │ ├── console.js │ ├── jasmine-html.js │ ├── jasmine.css │ ├── mock-ajax.js │ ├── jasmine-jquery.js │ └── jquery-3.1.0.min.js ├── src ├── utils.js ├── main.js ├── read.js ├── write.js └── url_utils.js ├── package.json ├── ProductionReadySpecRunner.html ├── SpecRunner.html └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | test_page*.html 2 | .idea/ 3 | deploy.sh 4 | -------------------------------------------------------------------------------- /spec/SpecHelper.js: -------------------------------------------------------------------------------- 1 | function cl(string) { 2 | console.log(string); 3 | } 4 | -------------------------------------------------------------------------------- /images/step-1-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sheetdb/sheetsu-web-client/HEAD/images/step-1-1.png -------------------------------------------------------------------------------- /images/step-1-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sheetdb/sheetsu-web-client/HEAD/images/step-1-2.png -------------------------------------------------------------------------------- /images/step-1-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sheetdb/sheetsu-web-client/HEAD/images/step-1-3.png -------------------------------------------------------------------------------- /images/step-2-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sheetdb/sheetsu-web-client/HEAD/images/step-2-1.png -------------------------------------------------------------------------------- /images/step-2-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sheetdb/sheetsu-web-client/HEAD/images/step-2-2.png -------------------------------------------------------------------------------- /images/step-3-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sheetdb/sheetsu-web-client/HEAD/images/step-3-1.png -------------------------------------------------------------------------------- /images/step-3-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sheetdb/sheetsu-web-client/HEAD/images/step-3-2.png -------------------------------------------------------------------------------- /images/step-3-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sheetdb/sheetsu-web-client/HEAD/images/step-3-3.png -------------------------------------------------------------------------------- /lib/jasmine-2.4.1/jasmine_favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sheetdb/sheetsu-web-client/HEAD/lib/jasmine-2.4.1/jasmine_favicon.png -------------------------------------------------------------------------------- /src/utils.js: -------------------------------------------------------------------------------- 1 | if (!String.prototype.startsWith) { 2 | String.prototype.startsWith = function(searchString, position) { 3 | position = position || 0; 4 | return this.indexOf(searchString, position) === position; 5 | }; 6 | } 7 | -------------------------------------------------------------------------------- /src/main.js: -------------------------------------------------------------------------------- 1 | Sheetsu = { 2 | read: function(){ 3 | if (arguments.length == 2) 4 | return readWithPromise.apply(null, arguments); 5 | return read.apply(null, arguments); 6 | }, 7 | write: function(){ 8 | if (arguments.length == 3) 9 | return writeWithPromise.apply(null, arguments); 10 | return write.apply(null, arguments); 11 | }, 12 | version: "1.0" 13 | } 14 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "sheetsu-web-client", 3 | "version": "1.0.0", 4 | "description": "Google Spreadsheets as a website database. Store, edit and analyse data even with no knowledge of SQL. With few lines of code you can read and write data to Google Spreadsheets.", 5 | "main": "build/sheetsu-web-client.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "git+https://github.com/sheetsu/sheetsu-web-client.git" 12 | }, 13 | "keywords": [ 14 | "sheetsu", 15 | "google", 16 | "spreadsheet", 17 | "drive" 18 | ], 19 | "author": "Michael Oblak", 20 | "license": "MIT", 21 | "bugs": { 22 | "url": "https://github.com/sheetsu/sheetsu-web-client/issues" 23 | }, 24 | "homepage": "https://github.com/sheetsu/sheetsu-web-client#readme" 25 | } 26 | -------------------------------------------------------------------------------- /ProductionReadySpecRunner.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Jasmine Spec Runner v2.4.1 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /SpecRunner.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Jasmine Spec Runner v2.4.1 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /src/read.js: -------------------------------------------------------------------------------- 1 | function read(slug_or_url, options, successFunction) { 2 | var xhr = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject("Microsoft.XMLHTTP"); 3 | 4 | xhr.onreadystatechange = function() { 5 | if (xhr.readyState > 3 && xhr.status == 200) { 6 | successFunction(JSON.parse(xhr.responseText)); 7 | } 8 | } 9 | 10 | xhr.open("GET", sheetsuUrlGet(slug_or_url, options), true); 11 | xhr.send(); 12 | }; 13 | 14 | function readWithPromise(slug_or_url, options) { 15 | return new Promise(function (resolve, reject) { 16 | var xhr = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject("Microsoft.XMLHTTP"); 17 | xhr.open("GET", sheetsuUrlGet(slug_or_url, options), true); 18 | xhr.onload = function () { 19 | if (this.status >= 200 && this.status < 300) { 20 | resolve(JSON.parse(xhr.responseText)); 21 | } else { 22 | reject({ 23 | status: this.status, 24 | statusText: xhr.statusText 25 | }); 26 | } 27 | }; 28 | 29 | xhr.setRequestHeader("Accept", "application/vnd.sheetsu.3+json"); 30 | xhr.setRequestHeader("Content-Type", "application/json"); 31 | xhr.setRequestHeader("X-User-Agent", "Sheetsu-JS"); 32 | xhr.onerror = function (e) { 33 | reject(e); 34 | }; 35 | 36 | xhr.send(); 37 | }); 38 | } 39 | -------------------------------------------------------------------------------- /src/write.js: -------------------------------------------------------------------------------- 1 | function write(slug_or_url, data, options, successFunction, errorFunction) { 2 | var xhr = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject("Microsoft.XMLHTTP"); 3 | 4 | xhr.onreadystatechange = function() { 5 | if (xhr.readyState > 3 && xhr.status == 201) { 6 | successFunction(JSON.parse(xhr.responseText)); 7 | } else { 8 | if (errorFunction != undefined) { 9 | errorFunction(xhr.responseText); 10 | } 11 | } 12 | } 13 | 14 | xhr.open("POST", sheetsuUrlPost(slug_or_url, options), true); 15 | xhr.setRequestHeader('Content-Type', 'application/json; charset=UTF-8'); 16 | xhr.send(JSON.stringify(data)); 17 | } 18 | 19 | function writeWithPromise(slug_or_url, data, options) { 20 | return new Promise(function (resolve, reject) { 21 | var xhr = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject("Microsoft.XMLHTTP"); 22 | xhr.open("POST", sheetsuUrlPost(slug_or_url, options), true); 23 | xhr.onload = function () { 24 | if (this.status >= 200 && this.status < 300) { 25 | resolve(JSON.parse(xhr.responseText)); 26 | } else { 27 | reject({ 28 | status: this.status, 29 | statusText: xhr.statusText 30 | }); 31 | } 32 | }; 33 | 34 | xhr.setRequestHeader("Accept", "application/vnd.sheetsu.3+json"); 35 | xhr.setRequestHeader('Content-Type', 'application/json; charset=UTF-8'); 36 | xhr.setRequestHeader("X-User-Agent", "Sheetsu-JS"); 37 | xhr.onerror = function (e) { 38 | reject(e); 39 | }; 40 | 41 | xhr.send(JSON.stringify(data)); 42 | }); 43 | } 44 | -------------------------------------------------------------------------------- /src/url_utils.js: -------------------------------------------------------------------------------- 1 | var sheetsuUrlGet = function(slug_or_url, options) { 2 | var url = sheetsuUrl(slug_or_url), 3 | pathQueryString = "", 4 | limit_offset_transposed = addLimitOffsetTransposed(options); 5 | 6 | if (options["sheet"]) { 7 | pathQueryString += sheet(options); 8 | } 9 | 10 | if (options["search"]) { 11 | pathQueryString += search(options); 12 | } 13 | 14 | if (limit_offset_transposed != "") { 15 | if (options["search"]) { 16 | pathQueryString += ("&" + limit_offset_transposed); 17 | } else { 18 | pathQueryString += ("?" + limit_offset_transposed); 19 | } 20 | } 21 | 22 | return (url + pathQueryString); 23 | }; 24 | 25 | var sheetsuUrlPost = function(slug_or_url, options) { 26 | var url = sheetsuUrl(slug_or_url), 27 | pathQueryString = ""; 28 | 29 | if (options["sheet"]) { 30 | pathQueryString += sheet(options); 31 | } 32 | 33 | return (url + pathQueryString); 34 | }; 35 | 36 | var sheetsuUrl = function(urlOrSlug) { 37 | if (urlOrSlug.startsWith("https://sheetsu.com/apis/v1.0")) { 38 | return urlOrSlug; 39 | } else { 40 | return ("https://sheetsu.com/apis/v1.0ow/" + urlOrSlug); 41 | } 42 | }; 43 | 44 | var search = function(options) { 45 | var searchQuery = [], 46 | searchParams = options["search"]; 47 | 48 | for (key in searchParams) { searchQuery.push(key + "=" + searchParams[key]); }; 49 | return ("/search?" + searchQuery.join("&")); 50 | }; 51 | 52 | var sheet = function(options) { 53 | return ("/sheets/" + options["sheet"]); 54 | }; 55 | 56 | var addLimitOffsetTransposed = function(options) { 57 | var queryOptions = []; 58 | if (options["limit"]) { queryOptions.push("limit=" + options["limit"]); }; 59 | if (options["offset"]) { queryOptions.push("offset=" + options["offset"]); }; 60 | if (options["transposed"]) { queryOptions.push("transposed=" + options["transposed"]); }; 61 | if (options["ignore_case"]) { queryOptions.push("ignore_case=" + options["ignore_case"]); }; 62 | 63 | return queryOptions.join("&"); 64 | }; 65 | -------------------------------------------------------------------------------- /spec/WriteSpec.js: -------------------------------------------------------------------------------- 1 | describe("Sheetsu.write", function() { 2 | var doneFn, errorFn; 3 | 4 | beforeEach(function() { 5 | jasmine.Ajax.install(); 6 | doneFn = jasmine.createSpy("success"); 7 | errorFn = jasmine.createSpy("error"); 8 | }); 9 | 10 | afterEach(function() { 11 | jasmine.Ajax.uninstall(); 12 | }); 13 | 14 | describe("a POST request", function() { 15 | it("should be performed", function() { 16 | Sheetsu.write("deadbeef69", { "name": "hippo", "sound": "growl" }, {}, doneFn); 17 | 18 | expect(jasmine.Ajax.requests.mostRecent().url).toBe("https://sheetsu.com/apis/v1.0/deadbeef69"); 19 | expect(jasmine.Ajax.requests.mostRecent().method).toBe("POST"); 20 | expect(JSON.parse(jasmine.Ajax.requests.mostRecent().params)).toEqual({ "name": "hippo", "sound": "growl" }); 21 | }); 22 | 23 | it("should be performed to proper URL", function() { 24 | Sheetsu.write("https://sheetsu.com/apis/v1.0/deadbeef69", { "name": "hippo", "sound": "growl" }, {}, doneFn); 25 | 26 | expect(jasmine.Ajax.requests.mostRecent().url).toBe("https://sheetsu.com/apis/v1.0/deadbeef69"); 27 | expect(jasmine.Ajax.requests.mostRecent().method).toBe("POST"); 28 | expect(JSON.parse(jasmine.Ajax.requests.mostRecent().params)).toEqual({ "name": "hippo", "sound": "growl" }); 29 | }); 30 | 31 | it("should perform POST to a worksheet", function() { 32 | Sheetsu.write("deadbeef69", { "name": "hippo", "sound": "growl" }, { "sheet": "Sheet1" }, doneFn); 33 | 34 | expect(jasmine.Ajax.requests.mostRecent().url).toBe("https://sheetsu.com/apis/v1.0/deadbeef69/sheets/Sheet1"); 35 | expect(jasmine.Ajax.requests.mostRecent().method).toBe("POST"); 36 | expect(JSON.parse(jasmine.Ajax.requests.mostRecent().params)).toEqual({ "name": "hippo", "sound": "growl" }); 37 | }); 38 | 39 | it("should send a few rows", function() { 40 | var data = [ 41 | { "name": "hippo", "sound": "growl" }, 42 | { "name": "dog", "sound": "woff" }, 43 | { "name": "cat", "sound": "meow" }, 44 | ]; 45 | Sheetsu.write("https://sheetsu.com/apis/v1.0/deadbeef69", data, {}, doneFn); 46 | 47 | expect(jasmine.Ajax.requests.mostRecent().url).toBe("https://sheetsu.com/apis/v1.0/deadbeef69"); 48 | expect(jasmine.Ajax.requests.mostRecent().method).toBe("POST"); 49 | expect(JSON.parse(jasmine.Ajax.requests.mostRecent().params)).toEqual(data); 50 | }); 51 | 52 | it("should run success function on success", function() { 53 | jasmine.Ajax.stubRequest('https://sheetsu.com/apis/v1.0/deadbeef69').andReturn({ 54 | "responseText": "{ \"foo\": \"bar\" }", 55 | "status": 201 56 | }); 57 | 58 | Sheetsu.write("deadbeef69", { "name": "hippo", "sound": "growl" }, {}, doneFn); 59 | 60 | expect(doneFn).toHaveBeenCalled(); 61 | }); 62 | 63 | it("should run error function on error", function() { 64 | jasmine.Ajax.stubRequest('https://sheetsu.com/apis/v1.0/deadbeef69').andReturn({ 65 | "responseText": "{ \"error\": \"Something went wrong\" }", 66 | "status": 400 67 | }); 68 | 69 | Sheetsu.write("deadbeef69", { "name": "hippo", "sound": "growl" }, {}, doneFn, errorFn); 70 | 71 | expect(errorFn).toHaveBeenCalled(); 72 | }); 73 | 74 | describe("with promise", function() { 75 | var url; 76 | var expectedResponse; 77 | var expectedValue; 78 | 79 | beforeEach(function(done) { 80 | expectedResponse = JSON.stringify({TestColumn: 'A'}); 81 | url = "https://sheetsu.com/apis/v1.0/deadbeef69"; 82 | jasmine.Ajax.stubRequest(url).andReturn({ 83 | "status": 200, 84 | "contentType": "application/json", 85 | "responseText": expectedResponse 86 | }); 87 | 88 | Sheetsu 89 | .write(url, JSON.parse(expectedResponse), {}) 90 | .then(function(data){ 91 | expectedValue = data; 92 | done(); 93 | }); 94 | }); 95 | 96 | it("should be called with proper url and method", function() { 97 | expect(jasmine.Ajax.requests.mostRecent().url).toBe(url); 98 | expect(jasmine.Ajax.requests.mostRecent().method).toBe("POST"); 99 | }); 100 | 101 | it("should return value in then", function() { 102 | expect(expectedValue).toEqual(JSON.parse(expectedResponse)); 103 | }); 104 | 105 | }); 106 | }); 107 | }); 108 | -------------------------------------------------------------------------------- /lib/jasmine-2.4.1/boot.js: -------------------------------------------------------------------------------- 1 | /** 2 | Starting with version 2.0, this file "boots" Jasmine, performing all of the necessary initialization before executing the loaded environment and all of a project's specs. This file should be loaded after `jasmine.js` and `jasmine_html.js`, but before any project source files or spec files are loaded. Thus this file can also be used to customize Jasmine for a project. 3 | 4 | If a project is using Jasmine via the standalone distribution, this file can be customized directly. If a project is using Jasmine via the [Ruby gem][jasmine-gem], this file can be copied into the support directory via `jasmine copy_boot_js`. Other environments (e.g., Python) will have different mechanisms. 5 | 6 | The location of `boot.js` can be specified and/or overridden in `jasmine.yml`. 7 | 8 | [jasmine-gem]: http://github.com/pivotal/jasmine-gem 9 | */ 10 | 11 | (function() { 12 | 13 | /** 14 | * ## Require & Instantiate 15 | * 16 | * Require Jasmine's core files. Specifically, this requires and attaches all of Jasmine's code to the `jasmine` reference. 17 | */ 18 | window.jasmine = jasmineRequire.core(jasmineRequire); 19 | 20 | /** 21 | * Since this is being run in a browser and the results should populate to an HTML page, require the HTML-specific Jasmine code, injecting the same reference. 22 | */ 23 | jasmineRequire.html(jasmine); 24 | 25 | /** 26 | * Create the Jasmine environment. This is used to run all specs in a project. 27 | */ 28 | var env = jasmine.getEnv(); 29 | 30 | /** 31 | * ## The Global Interface 32 | * 33 | * Build up the functions that will be exposed as the Jasmine public interface. A project can customize, rename or alias any of these functions as desired, provided the implementation remains unchanged. 34 | */ 35 | var jasmineInterface = jasmineRequire.interface(jasmine, env); 36 | 37 | /** 38 | * Add all of the Jasmine global/public interface to the global scope, so a project can use the public interface directly. For example, calling `describe` in specs instead of `jasmine.getEnv().describe`. 39 | */ 40 | extend(window, jasmineInterface); 41 | 42 | /** 43 | * ## Runner Parameters 44 | * 45 | * More browser specific code - wrap the query string in an object and to allow for getting/setting parameters from the runner user interface. 46 | */ 47 | 48 | var queryString = new jasmine.QueryString({ 49 | getWindowLocation: function() { return window.location; } 50 | }); 51 | 52 | var catchingExceptions = queryString.getParam("catch"); 53 | env.catchExceptions(typeof catchingExceptions === "undefined" ? true : catchingExceptions); 54 | 55 | var throwingExpectationFailures = queryString.getParam("throwFailures"); 56 | env.throwOnExpectationFailure(throwingExpectationFailures); 57 | 58 | var random = queryString.getParam("random"); 59 | env.randomizeTests(random); 60 | 61 | var seed = queryString.getParam("seed"); 62 | if (seed) { 63 | env.seed(seed); 64 | } 65 | 66 | /** 67 | * ## Reporters 68 | * The `HtmlReporter` builds all of the HTML UI for the runner page. This reporter paints the dots, stars, and x's for specs, as well as all spec names and all failures (if any). 69 | */ 70 | var htmlReporter = new jasmine.HtmlReporter({ 71 | env: env, 72 | onRaiseExceptionsClick: function() { queryString.navigateWithNewParam("catch", !env.catchingExceptions()); }, 73 | onThrowExpectationsClick: function() { queryString.navigateWithNewParam("throwFailures", !env.throwingExpectationFailures()); }, 74 | onRandomClick: function() { queryString.navigateWithNewParam("random", !env.randomTests()); }, 75 | addToExistingQueryString: function(key, value) { return queryString.fullStringWithNewParam(key, value); }, 76 | getContainer: function() { return document.body; }, 77 | createElement: function() { return document.createElement.apply(document, arguments); }, 78 | createTextNode: function() { return document.createTextNode.apply(document, arguments); }, 79 | timer: new jasmine.Timer() 80 | }); 81 | 82 | /** 83 | * The `jsApiReporter` also receives spec results, and is used by any environment that needs to extract the results from JavaScript. 84 | */ 85 | env.addReporter(jasmineInterface.jsApiReporter); 86 | env.addReporter(htmlReporter); 87 | 88 | /** 89 | * Filter which specs will be run by matching the start of the full name against the `spec` query param. 90 | */ 91 | var specFilter = new jasmine.HtmlSpecFilter({ 92 | filterString: function() { return queryString.getParam("spec"); } 93 | }); 94 | 95 | env.specFilter = function(spec) { 96 | return specFilter.matches(spec.getFullName()); 97 | }; 98 | 99 | /** 100 | * Setting up timing functions to be able to be overridden. Certain browsers (Safari, IE 8, phantomjs) require this hack. 101 | */ 102 | window.setTimeout = window.setTimeout; 103 | window.setInterval = window.setInterval; 104 | window.clearTimeout = window.clearTimeout; 105 | window.clearInterval = window.clearInterval; 106 | 107 | /** 108 | * ## Execution 109 | * 110 | * Replace the browser window's `onload`, ensure it's called, and then run all of the loaded specs. This includes initializing the `HtmlReporter` instance and then executing the loaded Jasmine environment. All of this will happen after all of the specs are loaded. 111 | */ 112 | var currentWindowOnload = window.onload; 113 | 114 | window.onload = function() { 115 | if (currentWindowOnload) { 116 | currentWindowOnload(); 117 | } 118 | htmlReporter.initialize(); 119 | env.execute(); 120 | }; 121 | 122 | /** 123 | * Helper function for readability above. 124 | */ 125 | function extend(destination, source) { 126 | for (var property in source) destination[property] = source[property]; 127 | return destination; 128 | } 129 | 130 | }()); 131 | -------------------------------------------------------------------------------- /lib/jasmine-2.4.1/console.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2008-2015 Pivotal Labs 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining 5 | a copy of this software and associated documentation files (the 6 | "Software"), to deal in the Software without restriction, including 7 | without limitation the rights to use, copy, modify, merge, publish, 8 | distribute, sublicense, and/or sell copies of the Software, and to 9 | permit persons to whom the Software is furnished to do so, subject to 10 | the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be 13 | included in all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 19 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 20 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 21 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | */ 23 | function getJasmineRequireObj() { 24 | if (typeof module !== 'undefined' && module.exports) { 25 | return exports; 26 | } else { 27 | window.jasmineRequire = window.jasmineRequire || {}; 28 | return window.jasmineRequire; 29 | } 30 | } 31 | 32 | getJasmineRequireObj().console = function(jRequire, j$) { 33 | j$.ConsoleReporter = jRequire.ConsoleReporter(); 34 | }; 35 | 36 | getJasmineRequireObj().ConsoleReporter = function() { 37 | 38 | var noopTimer = { 39 | start: function(){}, 40 | elapsed: function(){ return 0; } 41 | }; 42 | 43 | function ConsoleReporter(options) { 44 | var print = options.print, 45 | showColors = options.showColors || false, 46 | onComplete = options.onComplete || function() {}, 47 | timer = options.timer || noopTimer, 48 | specCount, 49 | failureCount, 50 | failedSpecs = [], 51 | pendingCount, 52 | ansi = { 53 | green: '\x1B[32m', 54 | red: '\x1B[31m', 55 | yellow: '\x1B[33m', 56 | none: '\x1B[0m' 57 | }, 58 | failedSuites = []; 59 | 60 | print('ConsoleReporter is deprecated and will be removed in a future version.'); 61 | 62 | this.jasmineStarted = function() { 63 | specCount = 0; 64 | failureCount = 0; 65 | pendingCount = 0; 66 | print('Started'); 67 | printNewline(); 68 | timer.start(); 69 | }; 70 | 71 | this.jasmineDone = function() { 72 | printNewline(); 73 | for (var i = 0; i < failedSpecs.length; i++) { 74 | specFailureDetails(failedSpecs[i]); 75 | } 76 | 77 | if(specCount > 0) { 78 | printNewline(); 79 | 80 | var specCounts = specCount + ' ' + plural('spec', specCount) + ', ' + 81 | failureCount + ' ' + plural('failure', failureCount); 82 | 83 | if (pendingCount) { 84 | specCounts += ', ' + pendingCount + ' pending ' + plural('spec', pendingCount); 85 | } 86 | 87 | print(specCounts); 88 | } else { 89 | print('No specs found'); 90 | } 91 | 92 | printNewline(); 93 | var seconds = timer.elapsed() / 1000; 94 | print('Finished in ' + seconds + ' ' + plural('second', seconds)); 95 | printNewline(); 96 | 97 | for(i = 0; i < failedSuites.length; i++) { 98 | suiteFailureDetails(failedSuites[i]); 99 | } 100 | 101 | onComplete(failureCount === 0); 102 | }; 103 | 104 | this.specDone = function(result) { 105 | specCount++; 106 | 107 | if (result.status == 'pending') { 108 | pendingCount++; 109 | print(colored('yellow', '*')); 110 | return; 111 | } 112 | 113 | if (result.status == 'passed') { 114 | print(colored('green', '.')); 115 | return; 116 | } 117 | 118 | if (result.status == 'failed') { 119 | failureCount++; 120 | failedSpecs.push(result); 121 | print(colored('red', 'F')); 122 | } 123 | }; 124 | 125 | this.suiteDone = function(result) { 126 | if (result.failedExpectations && result.failedExpectations.length > 0) { 127 | failureCount++; 128 | failedSuites.push(result); 129 | } 130 | }; 131 | 132 | return this; 133 | 134 | function printNewline() { 135 | print('\n'); 136 | } 137 | 138 | function colored(color, str) { 139 | return showColors ? (ansi[color] + str + ansi.none) : str; 140 | } 141 | 142 | function plural(str, count) { 143 | return count == 1 ? str : str + 's'; 144 | } 145 | 146 | function repeat(thing, times) { 147 | var arr = []; 148 | for (var i = 0; i < times; i++) { 149 | arr.push(thing); 150 | } 151 | return arr; 152 | } 153 | 154 | function indent(str, spaces) { 155 | var lines = (str || '').split('\n'); 156 | var newArr = []; 157 | for (var i = 0; i < lines.length; i++) { 158 | newArr.push(repeat(' ', spaces).join('') + lines[i]); 159 | } 160 | return newArr.join('\n'); 161 | } 162 | 163 | function specFailureDetails(result) { 164 | printNewline(); 165 | print(result.fullName); 166 | 167 | for (var i = 0; i < result.failedExpectations.length; i++) { 168 | var failedExpectation = result.failedExpectations[i]; 169 | printNewline(); 170 | print(indent(failedExpectation.message, 2)); 171 | print(indent(failedExpectation.stack, 2)); 172 | } 173 | 174 | printNewline(); 175 | } 176 | 177 | function suiteFailureDetails(result) { 178 | for (var i = 0; i < result.failedExpectations.length; i++) { 179 | printNewline(); 180 | print(colored('red', 'An error was thrown in an afterAll')); 181 | printNewline(); 182 | print(colored('red', 'AfterAll ' + result.failedExpectations[i].message)); 183 | 184 | } 185 | printNewline(); 186 | } 187 | } 188 | 189 | return ConsoleReporter; 190 | }; 191 | -------------------------------------------------------------------------------- /spec/ReadSpec.js: -------------------------------------------------------------------------------- 1 | describe("Sheetsu.read", function() { 2 | var doneFn = jasmine.createSpy("success"); 3 | 4 | beforeEach(function() { 5 | jasmine.Ajax.install(); 6 | }); 7 | 8 | afterEach(function() { 9 | jasmine.Ajax.uninstall(); 10 | }); 11 | 12 | describe("it should perform a GET request", function() { 13 | it("with correct params", function() { 14 | Sheetsu.read("deadbeef", {}, doneFn); 15 | 16 | expect(jasmine.Ajax.requests.mostRecent().url).toBe("https://sheetsu.com/apis/v1.0/deadbeef"); 17 | expect(jasmine.Ajax.requests.mostRecent().method).toBe("GET"); 18 | }); 19 | 20 | it("to correct URL", function() { 21 | Sheetsu.read("deadbeef69", {}, doneFn); 22 | 23 | expect(jasmine.Ajax.requests.mostRecent().url).toBe("https://sheetsu.com/apis/v1.0/deadbeef69"); 24 | expect(jasmine.Ajax.requests.mostRecent().method).toBe("GET"); 25 | }); 26 | 27 | it("should call success function with JSON array", function(){ 28 | jasmine.Ajax.stubRequest("https://sheetsu.com/apis/v1.0/deadbeef69").andReturn({ 29 | "status": 200, 30 | "contentType": "application/json", 31 | "responseText": "[{\"TestColumn\":\"A\"},{\"TestColumn\":\"B\"},{\"TestColumn\":\"C\"},{\"TestColumn\":\"D\"}]" 32 | }); 33 | 34 | Sheetsu.read("deadbeef69", {}, doneFn); 35 | 36 | expect(doneFn).toHaveBeenCalledWith([{"TestColumn":"A"},{"TestColumn":"B"},{"TestColumn":"C"},{"TestColumn":"D"}]); 37 | }); 38 | 39 | describe("should perform correct request with options", function(){ 40 | it("sheet", function() { 41 | Sheetsu.read("deadbeef69", { "sheet": "animals" }, doneFn); 42 | 43 | expect(jasmine.Ajax.requests.mostRecent().url).toBe("https://sheetsu.com/apis/v1.0/deadbeef69/sheets/animals"); 44 | expect(jasmine.Ajax.requests.mostRecent().method).toBe("GET"); 45 | }); 46 | 47 | it("limit", function() { 48 | Sheetsu.read("deadbeef69", { "limit": "3" }, doneFn); 49 | 50 | expect(jasmine.Ajax.requests.mostRecent().url).toBe("https://sheetsu.com/apis/v1.0/deadbeef69?limit=3"); 51 | expect(jasmine.Ajax.requests.mostRecent().method).toBe("GET"); 52 | }); 53 | 54 | it("offset", function() { 55 | Sheetsu.read("deadbeef69", { "offset": "1" }, doneFn); 56 | 57 | expect(jasmine.Ajax.requests.mostRecent().url).toBe("https://sheetsu.com/apis/v1.0/deadbeef69?offset=1"); 58 | expect(jasmine.Ajax.requests.mostRecent().method).toBe("GET"); 59 | }); 60 | 61 | it("ignore_case true", function() { 62 | Sheetsu.read("deadbeef69", { "ignore_case": "true" }, doneFn); 63 | 64 | expect(jasmine.Ajax.requests.mostRecent().url).toBe("https://sheetsu.com/apis/v1.0/deadbeef69?ignore_case=true"); 65 | expect(jasmine.Ajax.requests.mostRecent().method).toBe("GET"); 66 | }); 67 | 68 | it("ignore_case false", function() { 69 | Sheetsu.read("deadbeef69", { "ignore_case": "false" }, doneFn); 70 | 71 | expect(jasmine.Ajax.requests.mostRecent().url).toBe("https://sheetsu.com/apis/v1.0/deadbeef69?ignore_case=false"); 72 | expect(jasmine.Ajax.requests.mostRecent().method).toBe("GET"); 73 | }); 74 | 75 | it("transposed", function() { 76 | Sheetsu.read("deadbeef69", { "transposed": "true" }, doneFn); 77 | 78 | expect(jasmine.Ajax.requests.mostRecent().url).toBe("https://sheetsu.com/apis/v1.0/deadbeef69?transposed=true"); 79 | expect(jasmine.Ajax.requests.mostRecent().method).toBe("GET"); 80 | }); 81 | 82 | it("limit, offset and transposed", function() { 83 | Sheetsu.read("deadbeef69", { "limit": "1", "offset": "2", "transposed": "true" }, doneFn); 84 | 85 | expect(jasmine.Ajax.requests.mostRecent().url).toBe("https://sheetsu.com/apis/v1.0/deadbeef69?limit=1&offset=2&transposed=true"); 86 | expect(jasmine.Ajax.requests.mostRecent().method).toBe("GET"); 87 | }); 88 | 89 | it("/search", function() { 90 | Sheetsu.read("deadbeef69", { "search": { "name": "Peter", "score": "43" } }, doneFn); 91 | 92 | expect(jasmine.Ajax.requests.mostRecent().url).toBe("https://sheetsu.com/apis/v1.0/deadbeef69/search?name=Peter&score=43"); 93 | expect(jasmine.Ajax.requests.mostRecent().method).toBe("GET"); 94 | }); 95 | 96 | it("/search with offset", function() { 97 | Sheetsu.read("deadbeef69", { "search": { "name": "Peter", "score": "43" }, "offset": "3" }, doneFn); 98 | 99 | expect(jasmine.Ajax.requests.mostRecent().url).toBe("https://sheetsu.com/apis/v1.0/deadbeef69/search?name=Peter&score=43&offset=3"); 100 | expect(jasmine.Ajax.requests.mostRecent().method).toBe("GET"); 101 | }); 102 | 103 | it("/sheets/:sheet + limit + offset + transposed", function() { 104 | Sheetsu.read("deadbeef69", { "sheet": "animals", "limit": "1", "offset": "2", "transposed": "true" }, doneFn); 105 | 106 | expect(jasmine.Ajax.requests.mostRecent().url).toBe("https://sheetsu.com/apis/v1.0/deadbeef69/sheets/animals?limit=1&offset=2&transposed=true"); 107 | expect(jasmine.Ajax.requests.mostRecent().method).toBe("GET"); 108 | }); 109 | 110 | it("and return promise", function() { 111 | var expectedResponse = JSON.stringify("[{TestColumn: 'A'},{TestColumn: 'B'},{TestColumn:'C'},{TestColumn:'D'}]"); 112 | var url = "https://sheetsu.com/apis/v1.0/deadbeef69/sheets/animals?limit=1&offset=2&transposed=true"; 113 | jasmine.Ajax.stubRequest(url).andReturn({ 114 | "status": 200, 115 | "contentType": "application/json", 116 | "responseText": expectedResponse 117 | }); 118 | 119 | Sheetsu 120 | .read("deadbeef69", { "sheet": "animals", "limit": "1", "offset": "2", "transposed": "true" }) 121 | .then(function(data){ 122 | expect(data).toEqual(JSON.parse(expectedResponse)); 123 | }); 124 | 125 | expect(jasmine.Ajax.requests.mostRecent().url).toBe(url); 126 | expect(jasmine.Ajax.requests.mostRecent().method).toBe("GET"); 127 | }); 128 | }); 129 | }); 130 | }); 131 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Sheetsu Web Client 2 | 3 | Google Spreadsheets as a website database. Store, edit and analyse data even with no knowledge of SQL. 4 | With few lines of code you can read and write data to Google Spreadsheets. 5 | 6 | 7 | Quick start 8 | 1. [Read data from database](#read-data) 9 | 2. [Search](#search) 10 | 3. [Read and update HTML elements](#read-and-update-html-elements) 11 | 4. [Save data](#save-data) 12 | 5. [Plot chart](#plot-chart) 13 | 14 | Other 15 | - [Installation](#installation) 16 | - [What is Sheetsu?](#what-is-sheetsu) 17 | - [How to create Google Spreadsheets API?](#how-to-create-google-spreadsheets-api) 18 | - [Docs](#docs) 19 | 20 | [Go to Sheetsu website →](https://sheetsu.com) 21 | 22 | All examples shown below run on this [Google Spreadsheet file](https://docs.google.com/spreadsheets/d/1WTwXrh2ZDXmXATZlQIuapdv4ldyhJGZg7LX8GlzPdZw/edit?usp=sharing). 23 | 24 | ## Read data 25 | 26 | Read data from Google Spreadsheets anywhere on the web. It works with ALL website builders, browsers, and front-end technologies. 27 | 28 | ```html 29 | 30 | 31 | 32 | 33 | 34 | 35 | 52 | 53 | ``` 54 | [Play with the live version of the code on CodePen](https://codepen.io/sheetsu/pen/QqKaOG?editors=1111) 55 | 56 | ## Search 57 | 58 | Search Google Spreadsheets for a record that matches your criteria. 59 | 60 | ```html 61 | 62 | 63 | 64 | 65 | 66 | 67 | 84 | 85 | ``` 86 | [Play with the live version of the code on CodePen](https://codepen.io/sheetsu/pen/LzReOX?editors=1111) 87 | 88 | ## Read and update HTML elements 89 | 90 | Get elements from Google Spreadsheets and show them on the web. 91 | 92 | ```html 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 116 | 117 | ``` 118 | [Play with the live version of the code on CodePen](https://codepen.io/sheetsu/pen/veXppq?editors=1111) 119 | 120 | ## Save data 121 | 122 | Save data from the form to the Google Spreadsheets 123 | 124 | ```html 125 | 126 | 127 | 128 | 129 | 130 |
131 | 132 | 133 | 134 |
135 | 136 | 161 | 162 | ``` 163 | [Play with the live version of the code on CodePen](https://codepen.io/sheetsu/pen/gGwoeb?editors=1111) 164 | 165 | ## Plot chart 166 | 167 | Plot chart with [HighchartJS](https://www.highcharts.com/). 168 | 169 | ```html 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 |
178 | 179 | 197 | 198 | 199 | ``` 200 | [Play with the live version of the code on CodePen](https://codepen.io/sheetsu/pen/dVpJmr) 201 | 202 | # Installation 203 | To install Sheetsu Web Client, just add 204 | ``` 205 | 206 | ``` 207 | to the `` of a website. 208 | Or anywhere else. It should work anyway :) 209 | 210 | # What is Sheetsu 211 | 212 | [Sheetsu](https://sheetsu.com) is a connection between you and Google Spreadsheets, you can use **anywhere** on the web. You don't need to worry about authorization, refreshing tokens. You just speak with Google Spreadsheets, the easy language you know. 213 | 214 | [Go to Sheetsu website →](https://sheetsu.com) 215 | 216 | # How to create Google Spreadsheets API? 217 | ### 1. Create a new Google Spreadsheets file 218 | Open your browser and go to the [Google Spreadsheets site](https://docs.google.com/spreadsheets/u/0/). Create a new spreadsheet by clicking the "+" button. We will read data from this spreadsheet. 219 | 220 | ![Go to Google Spreadsheets](images/step-1-1.png) 221 | 222 | Name your new spreadsheet. 223 | 224 | ![Name spreadsheet](images/step-1-2.png) 225 | 226 | I named it "Example". Then add an example data. [You can copy them from this doc](https://docs.google.com/spreadsheets/d/1fW0JSTn2Jc3NkfuUkAn9aa_8kq-BqGVFOjp8lHzP8rc/edit#gid=0). Remember about naming columns first. 227 | 228 | ![Example data](images/step-1-3.png) 229 | 230 | ### 2. Go to Sheetsu.com and sign up 231 | When spreadsheet part is done, you need to [Sign up to Sheetsu](https://sheetsu.com). [Let's go to Sheetsu main page](https://sheetsu.com) and click "SIGN UP" button in top-right corner of the website. 232 | 233 | ![Sign up to Sheetsu](images/step-2-1.png) 234 | 235 | Sheetsu is using Google Authorization system, so you will be redirected to Google accounts page to give some permissions. 236 | 237 | ![Accept Google permissions](images/step-2-2.png) 238 | 239 | If you accept them, click ALLOW button. 240 | And puff! It is done! We are on the dashboard. 241 | 242 | ### 3. Copy API URL from Sheetsu 243 | To create an API you need to go back to your previously created spreadsheet and copy its URL. 244 | 245 | ![Copy Google Spreadsheets URL](images/step-3-1.png) 246 | 247 | And the last thing to do is to paste this URL in your dashboard and click "CREATE API" button. 248 | 249 | ![Create API](images/step-3-2.png) 250 | 251 | After that, your Sheetsu API will be created. You can click on a generatated link and see the results: 252 | 253 | ![API ready to use](images/step-3-3.png) 254 | 255 | ## Docs 256 | 257 | [Sheetsu documentation sits on GitHub](https://github.com/sheetsu/docs). We would love your contributions! We want to make these docs accessible and easy to understand for everyone. Please send us Pull Requests or open issues on GitHub. 258 | 259 | ### Sheetsu.read(url, options) 260 | Read data from Google Spreadsheet. Returns promis. `options` can be: 261 | ``` 262 | limit - number of how many rows should be returned 263 | offset - number from which row response should start (default is 0) 264 | transposed - transpose sheet on the fly. Default is false 265 | sheet - name of worksheet you want to access. Also, can be a number, worksheet sare numbered from 0. 266 | Example: 267 | { sheet: "Sheet2" } - read data from worksheet named 'Sheet2' 268 | { sheet: 3 } - read data from fourth worksheet 269 | search - object with search params to match searching criteria. Accepts '*' as a wildcard. 270 | Example: 271 | { search: { name: "Peter", score: 42 } } - return rows where name == Peter and score == 42 272 | { search: { name: "*is" } } - return rows where name ends with 'is' 273 | 274 | All options can be used together 275 | { sheet: "Sheet2", search: { foo: "bar" }, limit: 1 } - return first row only from worksheet named "Sheet2", where column 'foo' equals 'bar' 276 | ``` 277 | 278 | ### Sheetsu.write(url, data, options) 279 | Write data to Google Spreadsheet. Returns promis. `data` can be object - one row, or array similar to 280 | ``` 281 | { 282 | rows: [ 283 | { name: "X", score: "1" }, 284 | { name: "Y", score: "2" } 285 | ] 286 | } 287 | ``` 288 | if you want to save more than one row in a single request. 289 | `options` can be: 290 | ``` 291 | sheet - name of worksheet you want to access. Also, can be a number, worksheet sare numbered from 0. 292 | Example: 293 | { sheet: "Sheet2" } - read data from worksheet named 'Sheet2' 294 | { sheet: 3 } - read data from fourth worksheet 295 | ``` 296 | 297 | # Development 298 | 299 | To test this library open `SpecRunner.html` in a web browser. All specs are written with [Jasmine](https://jasmine.github.io/). Please keep in mind to keep this code as small as possible and to work on any kind of browser (yes, even old IE...). 300 | 301 | Run all tests: 302 | ```bash 303 | $ open `SpecRunner.html` 304 | ``` 305 | 306 | # Contributing 307 | 308 | Bug reports and pull requests are welcome on GitHub at https://github.com/sheetsu/sheetsu-js. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct. 309 | 310 | ### Pull Requests 311 | 312 | - **Add tests!** Your patch won't be accepted if it doesn't have tests. 313 | 314 | - **Create topic branches**. Please, always create a branch with meaningful name. Don't ask us to pull from your master branch. 315 | 316 | - **One pull request per feature**. If you want to do more than one thing, please send 317 | multiple pull requests. 318 | 319 | - **Send coherent history**. Make sure each individual commit in your pull 320 | request is meaningful. If you had to make multiple intermediate commits while 321 | developing, please squash them before sending them to us. 322 | -------------------------------------------------------------------------------- /lib/jasmine-2.4.1/jasmine-html.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2008-2015 Pivotal Labs 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining 5 | a copy of this software and associated documentation files (the 6 | "Software"), to deal in the Software without restriction, including 7 | without limitation the rights to use, copy, modify, merge, publish, 8 | distribute, sublicense, and/or sell copies of the Software, and to 9 | permit persons to whom the Software is furnished to do so, subject to 10 | the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be 13 | included in all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 19 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 20 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 21 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | */ 23 | jasmineRequire.html = function(j$) { 24 | j$.ResultsNode = jasmineRequire.ResultsNode(); 25 | j$.HtmlReporter = jasmineRequire.HtmlReporter(j$); 26 | j$.QueryString = jasmineRequire.QueryString(); 27 | j$.HtmlSpecFilter = jasmineRequire.HtmlSpecFilter(); 28 | }; 29 | 30 | jasmineRequire.HtmlReporter = function(j$) { 31 | 32 | var noopTimer = { 33 | start: function() {}, 34 | elapsed: function() { return 0; } 35 | }; 36 | 37 | function HtmlReporter(options) { 38 | var env = options.env || {}, 39 | getContainer = options.getContainer, 40 | createElement = options.createElement, 41 | createTextNode = options.createTextNode, 42 | onRaiseExceptionsClick = options.onRaiseExceptionsClick || function() {}, 43 | onThrowExpectationsClick = options.onThrowExpectationsClick || function() {}, 44 | onRandomClick = options.onRandomClick || function() {}, 45 | addToExistingQueryString = options.addToExistingQueryString || defaultQueryString, 46 | timer = options.timer || noopTimer, 47 | results = [], 48 | specsExecuted = 0, 49 | failureCount = 0, 50 | pendingSpecCount = 0, 51 | htmlReporterMain, 52 | symbols, 53 | failedSuites = []; 54 | 55 | this.initialize = function() { 56 | clearPrior(); 57 | htmlReporterMain = createDom('div', {className: 'jasmine_html-reporter'}, 58 | createDom('div', {className: 'jasmine-banner'}, 59 | createDom('a', {className: 'jasmine-title', href: 'http://jasmine.github.io/', target: '_blank'}), 60 | createDom('span', {className: 'jasmine-version'}, j$.version) 61 | ), 62 | createDom('ul', {className: 'jasmine-symbol-summary'}), 63 | createDom('div', {className: 'jasmine-alert'}), 64 | createDom('div', {className: 'jasmine-results'}, 65 | createDom('div', {className: 'jasmine-failures'}) 66 | ) 67 | ); 68 | getContainer().appendChild(htmlReporterMain); 69 | }; 70 | 71 | var totalSpecsDefined; 72 | this.jasmineStarted = function(options) { 73 | totalSpecsDefined = options.totalSpecsDefined || 0; 74 | timer.start(); 75 | }; 76 | 77 | var summary = createDom('div', {className: 'jasmine-summary'}); 78 | 79 | var topResults = new j$.ResultsNode({}, '', null), 80 | currentParent = topResults; 81 | 82 | this.suiteStarted = function(result) { 83 | currentParent.addChild(result, 'suite'); 84 | currentParent = currentParent.last(); 85 | }; 86 | 87 | this.suiteDone = function(result) { 88 | if (result.status == 'failed') { 89 | failedSuites.push(result); 90 | } 91 | 92 | if (currentParent == topResults) { 93 | return; 94 | } 95 | 96 | currentParent = currentParent.parent; 97 | }; 98 | 99 | this.specStarted = function(result) { 100 | currentParent.addChild(result, 'spec'); 101 | }; 102 | 103 | var failures = []; 104 | this.specDone = function(result) { 105 | if(noExpectations(result) && typeof console !== 'undefined' && typeof console.error !== 'undefined') { 106 | console.error('Spec \'' + result.fullName + '\' has no expectations.'); 107 | } 108 | 109 | if (result.status != 'disabled') { 110 | specsExecuted++; 111 | } 112 | 113 | if (!symbols){ 114 | symbols = find('.jasmine-symbol-summary'); 115 | } 116 | 117 | symbols.appendChild(createDom('li', { 118 | className: noExpectations(result) ? 'jasmine-empty' : 'jasmine-' + result.status, 119 | id: 'spec_' + result.id, 120 | title: result.fullName 121 | } 122 | )); 123 | 124 | if (result.status == 'failed') { 125 | failureCount++; 126 | 127 | var failure = 128 | createDom('div', {className: 'jasmine-spec-detail jasmine-failed'}, 129 | createDom('div', {className: 'jasmine-description'}, 130 | createDom('a', {title: result.fullName, href: specHref(result)}, result.fullName) 131 | ), 132 | createDom('div', {className: 'jasmine-messages'}) 133 | ); 134 | var messages = failure.childNodes[1]; 135 | 136 | for (var i = 0; i < result.failedExpectations.length; i++) { 137 | var expectation = result.failedExpectations[i]; 138 | messages.appendChild(createDom('div', {className: 'jasmine-result-message'}, expectation.message)); 139 | messages.appendChild(createDom('div', {className: 'jasmine-stack-trace'}, expectation.stack)); 140 | } 141 | 142 | failures.push(failure); 143 | } 144 | 145 | if (result.status == 'pending') { 146 | pendingSpecCount++; 147 | } 148 | }; 149 | 150 | this.jasmineDone = function(doneResult) { 151 | var banner = find('.jasmine-banner'); 152 | var alert = find('.jasmine-alert'); 153 | var order = doneResult && doneResult.order; 154 | alert.appendChild(createDom('span', {className: 'jasmine-duration'}, 'finished in ' + timer.elapsed() / 1000 + 's')); 155 | 156 | banner.appendChild( 157 | createDom('div', { className: 'jasmine-run-options' }, 158 | createDom('span', { className: 'jasmine-trigger' }, 'Options'), 159 | createDom('div', { className: 'jasmine-payload' }, 160 | createDom('div', { className: 'jasmine-exceptions' }, 161 | createDom('input', { 162 | className: 'jasmine-raise', 163 | id: 'jasmine-raise-exceptions', 164 | type: 'checkbox' 165 | }), 166 | createDom('label', { className: 'jasmine-label', 'for': 'jasmine-raise-exceptions' }, 'raise exceptions')), 167 | createDom('div', { className: 'jasmine-throw-failures' }, 168 | createDom('input', { 169 | className: 'jasmine-throw', 170 | id: 'jasmine-throw-failures', 171 | type: 'checkbox' 172 | }), 173 | createDom('label', { className: 'jasmine-label', 'for': 'jasmine-throw-failures' }, 'stop spec on expectation failure')), 174 | createDom('div', { className: 'jasmine-random-order' }, 175 | createDom('input', { 176 | className: 'jasmine-random', 177 | id: 'jasmine-random-order', 178 | type: 'checkbox' 179 | }), 180 | createDom('label', { className: 'jasmine-label', 'for': 'jasmine-random-order' }, 'run tests in random order')) 181 | ) 182 | )); 183 | 184 | var raiseCheckbox = find('#jasmine-raise-exceptions'); 185 | 186 | raiseCheckbox.checked = !env.catchingExceptions(); 187 | raiseCheckbox.onclick = onRaiseExceptionsClick; 188 | 189 | var throwCheckbox = find('#jasmine-throw-failures'); 190 | throwCheckbox.checked = env.throwingExpectationFailures(); 191 | throwCheckbox.onclick = onThrowExpectationsClick; 192 | 193 | var randomCheckbox = find('#jasmine-random-order'); 194 | randomCheckbox.checked = env.randomTests(); 195 | randomCheckbox.onclick = onRandomClick; 196 | 197 | var optionsMenu = find('.jasmine-run-options'), 198 | optionsTrigger = optionsMenu.querySelector('.jasmine-trigger'), 199 | optionsPayload = optionsMenu.querySelector('.jasmine-payload'), 200 | isOpen = /\bjasmine-open\b/; 201 | 202 | optionsTrigger.onclick = function() { 203 | if (isOpen.test(optionsPayload.className)) { 204 | optionsPayload.className = optionsPayload.className.replace(isOpen, ''); 205 | } else { 206 | optionsPayload.className += ' jasmine-open'; 207 | } 208 | }; 209 | 210 | if (specsExecuted < totalSpecsDefined) { 211 | var skippedMessage = 'Ran ' + specsExecuted + ' of ' + totalSpecsDefined + ' specs - run all'; 212 | alert.appendChild( 213 | createDom('span', {className: 'jasmine-bar jasmine-skipped'}, 214 | createDom('a', {href: '?', title: 'Run all specs'}, skippedMessage) 215 | ) 216 | ); 217 | } 218 | var statusBarMessage = ''; 219 | var statusBarClassName = 'jasmine-bar '; 220 | 221 | if (totalSpecsDefined > 0) { 222 | statusBarMessage += pluralize('spec', specsExecuted) + ', ' + pluralize('failure', failureCount); 223 | if (pendingSpecCount) { statusBarMessage += ', ' + pluralize('pending spec', pendingSpecCount); } 224 | statusBarClassName += (failureCount > 0) ? 'jasmine-failed' : 'jasmine-passed'; 225 | } else { 226 | statusBarClassName += 'jasmine-skipped'; 227 | statusBarMessage += 'No specs found'; 228 | } 229 | 230 | var seedBar; 231 | if (order && order.random) { 232 | seedBar = createDom('span', {className: 'jasmine-seed-bar'}, 233 | ', randomized with seed ', 234 | createDom('a', {title: 'randomized with seed ' + order.seed, href: seedHref(order.seed)}, order.seed) 235 | ); 236 | } 237 | 238 | alert.appendChild(createDom('span', {className: statusBarClassName}, statusBarMessage, seedBar)); 239 | 240 | for(i = 0; i < failedSuites.length; i++) { 241 | var failedSuite = failedSuites[i]; 242 | for(var j = 0; j < failedSuite.failedExpectations.length; j++) { 243 | var errorBarMessage = 'AfterAll ' + failedSuite.failedExpectations[j].message; 244 | var errorBarClassName = 'jasmine-bar jasmine-errored'; 245 | alert.appendChild(createDom('span', {className: errorBarClassName}, errorBarMessage)); 246 | } 247 | } 248 | 249 | var results = find('.jasmine-results'); 250 | results.appendChild(summary); 251 | 252 | summaryList(topResults, summary); 253 | 254 | function summaryList(resultsTree, domParent) { 255 | var specListNode; 256 | for (var i = 0; i < resultsTree.children.length; i++) { 257 | var resultNode = resultsTree.children[i]; 258 | if (resultNode.type == 'suite') { 259 | var suiteListNode = createDom('ul', {className: 'jasmine-suite', id: 'suite-' + resultNode.result.id}, 260 | createDom('li', {className: 'jasmine-suite-detail'}, 261 | createDom('a', {href: specHref(resultNode.result)}, resultNode.result.description) 262 | ) 263 | ); 264 | 265 | summaryList(resultNode, suiteListNode); 266 | domParent.appendChild(suiteListNode); 267 | } 268 | if (resultNode.type == 'spec') { 269 | if (domParent.getAttribute('class') != 'jasmine-specs') { 270 | specListNode = createDom('ul', {className: 'jasmine-specs'}); 271 | domParent.appendChild(specListNode); 272 | } 273 | var specDescription = resultNode.result.description; 274 | if(noExpectations(resultNode.result)) { 275 | specDescription = 'SPEC HAS NO EXPECTATIONS ' + specDescription; 276 | } 277 | if(resultNode.result.status === 'pending' && resultNode.result.pendingReason !== '') { 278 | specDescription = specDescription + ' PENDING WITH MESSAGE: ' + resultNode.result.pendingReason; 279 | } 280 | specListNode.appendChild( 281 | createDom('li', { 282 | className: 'jasmine-' + resultNode.result.status, 283 | id: 'spec-' + resultNode.result.id 284 | }, 285 | createDom('a', {href: specHref(resultNode.result)}, specDescription) 286 | ) 287 | ); 288 | } 289 | } 290 | } 291 | 292 | if (failures.length) { 293 | alert.appendChild( 294 | createDom('span', {className: 'jasmine-menu jasmine-bar jasmine-spec-list'}, 295 | createDom('span', {}, 'Spec List | '), 296 | createDom('a', {className: 'jasmine-failures-menu', href: '#'}, 'Failures'))); 297 | alert.appendChild( 298 | createDom('span', {className: 'jasmine-menu jasmine-bar jasmine-failure-list'}, 299 | createDom('a', {className: 'jasmine-spec-list-menu', href: '#'}, 'Spec List'), 300 | createDom('span', {}, ' | Failures '))); 301 | 302 | find('.jasmine-failures-menu').onclick = function() { 303 | setMenuModeTo('jasmine-failure-list'); 304 | }; 305 | find('.jasmine-spec-list-menu').onclick = function() { 306 | setMenuModeTo('jasmine-spec-list'); 307 | }; 308 | 309 | setMenuModeTo('jasmine-failure-list'); 310 | 311 | var failureNode = find('.jasmine-failures'); 312 | for (var i = 0; i < failures.length; i++) { 313 | failureNode.appendChild(failures[i]); 314 | } 315 | } 316 | }; 317 | 318 | return this; 319 | 320 | function find(selector) { 321 | return getContainer().querySelector('.jasmine_html-reporter ' + selector); 322 | } 323 | 324 | function clearPrior() { 325 | // return the reporter 326 | var oldReporter = find(''); 327 | 328 | if(oldReporter) { 329 | getContainer().removeChild(oldReporter); 330 | } 331 | } 332 | 333 | function createDom(type, attrs, childrenVarArgs) { 334 | var el = createElement(type); 335 | 336 | for (var i = 2; i < arguments.length; i++) { 337 | var child = arguments[i]; 338 | 339 | if (typeof child === 'string') { 340 | el.appendChild(createTextNode(child)); 341 | } else { 342 | if (child) { 343 | el.appendChild(child); 344 | } 345 | } 346 | } 347 | 348 | for (var attr in attrs) { 349 | if (attr == 'className') { 350 | el[attr] = attrs[attr]; 351 | } else { 352 | el.setAttribute(attr, attrs[attr]); 353 | } 354 | } 355 | 356 | return el; 357 | } 358 | 359 | function pluralize(singular, count) { 360 | var word = (count == 1 ? singular : singular + 's'); 361 | 362 | return '' + count + ' ' + word; 363 | } 364 | 365 | function specHref(result) { 366 | return addToExistingQueryString('spec', result.fullName); 367 | } 368 | 369 | function seedHref(seed) { 370 | return addToExistingQueryString('seed', seed); 371 | } 372 | 373 | function defaultQueryString(key, value) { 374 | return '?' + key + '=' + value; 375 | } 376 | 377 | function setMenuModeTo(mode) { 378 | htmlReporterMain.setAttribute('class', 'jasmine_html-reporter ' + mode); 379 | } 380 | 381 | function noExpectations(result) { 382 | return (result.failedExpectations.length + result.passedExpectations.length) === 0 && 383 | result.status === 'passed'; 384 | } 385 | } 386 | 387 | return HtmlReporter; 388 | }; 389 | 390 | jasmineRequire.HtmlSpecFilter = function() { 391 | function HtmlSpecFilter(options) { 392 | var filterString = options && options.filterString() && options.filterString().replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&'); 393 | var filterPattern = new RegExp(filterString); 394 | 395 | this.matches = function(specName) { 396 | return filterPattern.test(specName); 397 | }; 398 | } 399 | 400 | return HtmlSpecFilter; 401 | }; 402 | 403 | jasmineRequire.ResultsNode = function() { 404 | function ResultsNode(result, type, parent) { 405 | this.result = result; 406 | this.type = type; 407 | this.parent = parent; 408 | 409 | this.children = []; 410 | 411 | this.addChild = function(result, type) { 412 | this.children.push(new ResultsNode(result, type, this)); 413 | }; 414 | 415 | this.last = function() { 416 | return this.children[this.children.length - 1]; 417 | }; 418 | } 419 | 420 | return ResultsNode; 421 | }; 422 | 423 | jasmineRequire.QueryString = function() { 424 | function QueryString(options) { 425 | 426 | this.navigateWithNewParam = function(key, value) { 427 | options.getWindowLocation().search = this.fullStringWithNewParam(key, value); 428 | }; 429 | 430 | this.fullStringWithNewParam = function(key, value) { 431 | var paramMap = queryStringToParamMap(); 432 | paramMap[key] = value; 433 | return toQueryString(paramMap); 434 | }; 435 | 436 | this.getParam = function(key) { 437 | return queryStringToParamMap()[key]; 438 | }; 439 | 440 | return this; 441 | 442 | function toQueryString(paramMap) { 443 | var qStrPairs = []; 444 | for (var prop in paramMap) { 445 | qStrPairs.push(encodeURIComponent(prop) + '=' + encodeURIComponent(paramMap[prop])); 446 | } 447 | return '?' + qStrPairs.join('&'); 448 | } 449 | 450 | function queryStringToParamMap() { 451 | var paramStr = options.getWindowLocation().search.substring(1), 452 | params = [], 453 | paramMap = {}; 454 | 455 | if (paramStr.length > 0) { 456 | params = paramStr.split('&'); 457 | for (var i = 0; i < params.length; i++) { 458 | var p = params[i].split('='); 459 | var value = decodeURIComponent(p[1]); 460 | if (value === 'true' || value === 'false') { 461 | value = JSON.parse(value); 462 | } 463 | paramMap[decodeURIComponent(p[0])] = value; 464 | } 465 | } 466 | 467 | return paramMap; 468 | } 469 | 470 | } 471 | 472 | return QueryString; 473 | }; 474 | -------------------------------------------------------------------------------- /lib/jasmine-2.4.1/jasmine.css: -------------------------------------------------------------------------------- 1 | body { overflow-y: scroll; } 2 | 3 | .jasmine_html-reporter { background-color: #eee; padding: 5px; margin: -8px; font-size: 11px; font-family: Monaco, "Lucida Console", monospace; line-height: 14px; color: #333; } 4 | .jasmine_html-reporter a { text-decoration: none; } 5 | .jasmine_html-reporter a:hover { text-decoration: underline; } 6 | .jasmine_html-reporter p, .jasmine_html-reporter h1, .jasmine_html-reporter h2, .jasmine_html-reporter h3, .jasmine_html-reporter h4, .jasmine_html-reporter h5, .jasmine_html-reporter h6 { margin: 0; line-height: 14px; } 7 | .jasmine_html-reporter .jasmine-banner, .jasmine_html-reporter .jasmine-symbol-summary, .jasmine_html-reporter .jasmine-summary, .jasmine_html-reporter .jasmine-result-message, .jasmine_html-reporter .jasmine-spec .jasmine-description, .jasmine_html-reporter .jasmine-spec-detail .jasmine-description, .jasmine_html-reporter .jasmine-alert .jasmine-bar, .jasmine_html-reporter .jasmine-stack-trace { padding-left: 9px; padding-right: 9px; } 8 | .jasmine_html-reporter .jasmine-banner { position: relative; } 9 | .jasmine_html-reporter .jasmine-banner .jasmine-title { background: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFoAAAAZCAMAAACGusnyAAACdlBMVEX/////AP+AgICqVaqAQICZM5mAVYCSSZKAQICOOY6ATYCLRouAQICJO4mSSYCIRIiPQICHPIeOR4CGQ4aMQICGPYaLRoCFQ4WKQICPPYWJRYCOQoSJQICNPoSIRICMQoSHQICHRICKQoOHQICKPoOJO4OJQYOMQICMQ4CIQYKLQICIPoKLQ4CKQICNPoKJQISMQ4KJQoSLQYKJQISLQ4KIQoSKQYKIQICIQISMQoSKQYKLQIOLQoOJQYGLQIOKQIOMQoGKQYOLQYGKQIOLQoGJQYOJQIOKQYGJQIOKQoGKQIGLQIKLQ4KKQoGLQYKJQIGKQYKJQIGKQIKJQoGKQYKLQIGKQYKLQIOJQoKKQoOJQYKKQIOJQoKKQoOKQIOLQoKKQYOLQYKJQIOKQoKKQYKKQoKJQYOKQYKLQIOKQoKLQYOKQYKLQIOJQoGKQYKJQYGJQoGKQYKLQoGLQYGKQoGJQYKKQYGJQIKKQoGJQYKLQIKKQYGLQYKKQYGKQYGKQYKJQYOKQoKJQYOKQYKLQYOLQYOKQYKLQYOKQoKKQYKKQYOKQYOJQYKKQYKLQYKKQIKKQoKKQYKKQYKKQoKJQIKKQYKLQYKKQYKKQIKKQYKKQYKKQYKKQIKKQYKJQYGLQYGKQYKKQYKKQYGKQIKKQYGKQYOJQoKKQYOLQYKKQYOKQoKKQYKKQoKKQYKKQYKJQYKLQYKKQYKKQYKKQYKKQYKKQYKKQYKKQYKKQYKJQYKKQYKKQYKKQYKKQYKKQYKKQYKKQYKKQYKKQYKKQYKKQYKLQYKKQYKKQYKKQYKKQYKKQYKKQYKKQYKKQYKKQYKKQYKKQYKKQYKmIDpEAAAA0XRSTlMAAQIDBAUGBwgJCgsMDQ4PEBESExQVFhcYGRobHB0eHyAiIyQlJycoKissLS4wMTQ1Njc4OTo7PDw+P0BCQ0RISUpLTE1OUFNUVVdYWFlaW15fYGFiY2ZnaGlqa2xtb3BxcnN0dnh5ent8fX5/gIGChIWIioyNjo+QkZOUlZaYmZqbnJ2eoKGio6WmqKmsra6vsLGztre4ubq7vL2+wMHDxMjJysvNzs/Q0dLU1tfY2dvc3t/g4eLj5ebn6Onq6+zt7u/w8vP09fb3+Pn6+/z9/vkVQXAAAAMaSURBVHhe5dXxV1N1GMfxz2ABbDgIAm5VDJOyVDIJLUMaVpBWUZUaGbmqoGpZRSiGiRWp6KoZ5AB0ZY50RImZQIlahKkMYXv/R90dBvET/rJfOr3Ouc8v99zPec59zvf56j+vYKlViSf7250X4Mr3O29Tgq08BdGB4DhcekEJ5YkQKFsgWZdtj9JpV+I8xPjLFqkrsEIqO8PHSpis36jWazcqjEsfJjkvRssVU37SdIOu4XCf5vEJPsnwJpnRNU9JmxhMk8l1gehIrq7hTFjzOD+Vf88629qKMJVNltInFeRexRQyJlNeqd1iGDlSzrIUIyXbyFfm3RYprcQRe7lqtWyGYbfc6dT0R2vmdOOkX3u55C1rP37ftiH+tDby4r/RBT0w8TyEkr+epB9XgPDmSYYWbrhCuFYaIyw3fDQAXTnSkh+ANofiHmWf9l+FY1I90FdQTetstO00o23novzVsJ7uB3/C5TkbjRwZ5JerwV4iRWq9HFbFMaK/d0TYqayRiQPuIxxS3Bu8JWU90/60tKi7vkhaznez0a/TbVOKj5CaOZh6fWG6/Lyv9B/ZLR1gw/S/fpbeVD3MCW1li6SvWDOn65tr99/uvWtBS0XDm4s1t+sOHpG0kpBKx/l77wOSnxLpcx6TXmXLTPQOKYOf9Q1dfr8/SJ2mFdCvl1Yl93DiHUZvXeLJbGSzYu5gVJ2slbSakOR8dxCq5adQ2oFLqsE9Ex3L4qQO0eOPeU5x56bypXp4onSEb5OkICX6lDat55TeoztNKQcJaakrz9KCb95oD69IKq+yKW4XPjknaS52V0TZqE2cTtXjcHSCRmUO88e+85hj3EP74i9p8pylw7lxgMDyyl6OV7ZejnjNMfatu87LxRbH0IS35gt2a4ZjmGpVBdKK3Wr6INk8jWWSGqbA55CKgjBRC6E9w78ydTg3ABS3AFV1QN0Y4Aa2pgEjWnQURj9L0ayK6R2ysEqxHUKzYnLvvyU+i9KM2JHJzE4vyZOyDcOwOsySajeLPc8sNvPJkFlyJd20wpqAzZeAfZ3oWybxd+P/3j+SG3uSBdf2VQAAAABJRU5ErkJggg==') no-repeat; background: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjwhLS0gQ3JlYXRlZCB3aXRoIElua3NjYXBlIChodHRwOi8vd3d3Lmlua3NjYXBlLm9yZy8pIC0tPgoKPHN2ZwogICB4bWxuczpkYz0iaHR0cDovL3B1cmwub3JnL2RjL2VsZW1lbnRzLzEuMS8iCiAgIHhtbG5zOmNjPSJodHRwOi8vY3JlYXRpdmVjb21tb25zLm9yZy9ucyMiCiAgIHhtbG5zOnJkZj0iaHR0cDovL3d3dy53My5vcmcvMTk5OS8wMi8yMi1yZGYtc3ludGF4LW5zIyIKICAgeG1sbnM6c3ZnPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIKICAgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIgogICB4bWxuczppbmtzY2FwZT0iaHR0cDovL3d3dy5pbmtzY2FwZS5vcmcvbmFtZXNwYWNlcy9pbmtzY2FwZSIKICAgdmVyc2lvbj0iMS4xIgogICB3aWR0aD0iNjgxLjk2MjUyIgogICBoZWlnaHQ9IjE4Ny41IgogICBpZD0ic3ZnMiIKICAgeG1sOnNwYWNlPSJwcmVzZXJ2ZSI+PG1ldGFkYXRhCiAgICAgaWQ9Im1ldGFkYXRhOCI+PHJkZjpSREY+PGNjOldvcmsKICAgICAgICAgcmRmOmFib3V0PSIiPjxkYzpmb3JtYXQ+aW1hZ2Uvc3ZnK3htbDwvZGM6Zm9ybWF0PjxkYzp0eXBlCiAgICAgICAgICAgcmRmOnJlc291cmNlPSJodHRwOi8vcHVybC5vcmcvZGMvZGNtaXR5cGUvU3RpbGxJbWFnZSIgLz48L2NjOldvcms+PC9yZGY6UkRGPjwvbWV0YWRhdGE+PGRlZnMKICAgICBpZD0iZGVmczYiPjxjbGlwUGF0aAogICAgICAgaWQ9ImNsaXBQYXRoMTgiPjxwYXRoCiAgICAgICAgIGQ9Ik0gMCwxNTAwIDAsMCBsIDU0NTUuNzQsMCAwLDE1MDAgTCAwLDE1MDAgeiIKICAgICAgICAgaW5rc2NhcGU6Y29ubmVjdG9yLWN1cnZhdHVyZT0iMCIKICAgICAgICAgaWQ9InBhdGgyMCIgLz48L2NsaXBQYXRoPjwvZGVmcz48ZwogICAgIHRyYW5zZm9ybT0ibWF0cml4KDEuMjUsMCwwLC0xLjI1LDAsMTg3LjUpIgogICAgIGlkPSJnMTAiPjxnCiAgICAgICB0cmFuc2Zvcm09InNjYWxlKDAuMSwwLjEpIgogICAgICAgaWQ9ImcxMiI+PGcKICAgICAgICAgaWQ9ImcxNCI+PGcKICAgICAgICAgICBjbGlwLXBhdGg9InVybCgjY2xpcFBhdGgxOCkiCiAgICAgICAgICAgaWQ9ImcxNiI+PHBhdGgKICAgICAgICAgICAgIGQ9Im0gMTU0NCw1OTkuNDM0IGMgMC45MiwtNDAuMzUyIDI1LjY4LC04MS42MDIgNzEuNTMsLTgxLjYwMiAyNy41MSwwIDQ3LjY4LDEyLjgzMiA2MS40NCwzNS43NTQgMTIuODMsMjIuOTMgMTIuODMsNTYuODUyIDEyLjgzLDgyLjUyNyBsIDAsMzI5LjE4NCAtNzEuNTIsMCAwLDEwNC41NDMgMjY2LjgzLDAgMCwtMTA0LjU0MyAtNzAuNiwwIDAsLTM0NC43NyBjIDAsLTU4LjY5MSAtMy42OCwtMTA0LjUzMSAtNDQuOTMsLTE1Mi4yMTggLTM2LjY4LC00Mi4xOCAtOTYuMjgsLTY2LjAyIC0xNTMuMTQsLTY2LjAyIC0xMTcuMzcsMCAtMjA3LjI0LDc3Ljk0MSAtMjAyLjY0LDE5Ny4xNDUgbCAxMzAuMiwwIgogICAgICAgICAgICAgaW5rc2NhcGU6Y29ubmVjdG9yLWN1cnZhdHVyZT0iMCIKICAgICAgICAgICAgIGlkPSJwYXRoMjIiCiAgICAgICAgICAgICBzdHlsZT0iZmlsbDojOGE0MTgyO2ZpbGwtb3BhY2l0eToxO2ZpbGwtcnVsZTpub256ZXJvO3N0cm9rZTpub25lIiAvPjxwYXRoCiAgICAgICAgICAgICBkPSJtIDIzMDEuNCw2NjIuNjk1IGMgMCw4MC43MDMgLTY2Ljk0LDE0NS44MTMgLTE0Ny42MywxNDUuODEzIC04My40NCwwIC0xNDcuNjMsLTY4Ljc4MSAtMTQ3LjYzLC0xNTEuMzAxIDAsLTc5Ljc4NSA2Ni45NCwtMTQ1LjgwMSAxNDUuOCwtMTQ1LjgwMSA4NC4zNSwwIDE0OS40Niw2Ny44NTIgMTQ5LjQ2LDE1MS4yODkgeiBtIC0xLjgzLC0xODEuNTQ3IGMgLTM1Ljc3LC01NC4wOTcgLTkzLjUzLC03OC44NTkgLTE1Ny43MiwtNzguODU5IC0xNDAuMywwIC0yNTEuMjQsMTE2LjQ0OSAtMjUxLjI0LDI1NC45MTggMCwxNDIuMTI5IDExMy43LDI2MC40MSAyNTYuNzQsMjYwLjQxIDYzLjI3LDAgMTE4LjI5LC0yOS4zMzYgMTUyLjIyLC04Mi41MjMgbCAwLDY5LjY4NyAxNzUuMTQsMCAwLC0xMDQuNTI3IC02MS40NCwwIDAsLTI4MC41OTggNjEuNDQsMCAwLC0xMDQuNTI3IC0xNzUuMTQsMCAwLDY2LjAxOSIKICAgICAgICAgICAgIGlua3NjYXBlOmNvbm5lY3Rvci1jdXJ2YXR1cmU9IjAiCiAgICAgICAgICAgICBpZD0icGF0aDI0IgogICAgICAgICAgICAgc3R5bGU9ImZpbGw6IzhhNDE4MjtmaWxsLW9wYWNpdHk6MTtmaWxsLXJ1bGU6bm9uemVybztzdHJva2U6bm9uZSIgLz48cGF0aAogICAgICAgICAgICAgZD0ibSAyNjIyLjMzLDU1Ny4yNTggYyAzLjY3LC00NC4wMTYgMzMuMDEsLTczLjM0OCA3OC44NiwtNzMuMzQ4IDMzLjkzLDAgNjYuOTMsMjMuODI0IDY2LjkzLDYwLjUwNCAwLDQ4LjYwNiAtNDUuODQsNTYuODU2IC04My40NCw2Ni45NDEgLTg1LjI4LDIyLjAwNCAtMTc4LjgxLDQ4LjYwNiAtMTc4LjgxLDE1NS44NzkgMCw5My41MzYgNzguODYsMTQ3LjYzMyAxNjUuOTgsMTQ3LjYzMyA0NCwwIDgzLjQzLC05LjE3NiAxMTAuOTQsLTQ0LjAwOCBsIDAsMzMuOTIyIDgyLjUzLDAgMCwtMTMyLjk2NSAtMTA4LjIxLDAgYyAtMS44MywzNC44NTYgLTI4LjQyLDU3Ljc3NCAtNjMuMjYsNTcuNzc0IC0zMC4yNiwwIC02Mi4zNSwtMTcuNDIyIC02Mi4zNSwtNTEuMzQ4IDAsLTQ1Ljg0NyA0NC45MywtNTUuOTMgODAuNjksLTY0LjE4IDg4LjAyLC0yMC4xNzUgMTgyLjQ3LC00Ny42OTUgMTgyLjQ3LC0xNTcuNzM0IDAsLTk5LjAyNyAtODMuNDQsLTE1NC4wMzkgLTE3NS4xMywtMTU0LjAzOSAtNDkuNTMsMCAtOTQuNDYsMTUuNTgyIC0xMjYuNTUsNTMuMTggbCAwLC00MC4zNCAtODUuMjcsMCAwLDE0Mi4xMjkgMTE0LjYyLDAiCiAgICAgICAgICAgICBpbmtzY2FwZTpjb25uZWN0b3ItY3VydmF0dXJlPSIwIgogICAgICAgICAgICAgaWQ9InBhdGgyNiIKICAgICAgICAgICAgIHN0eWxlPSJmaWxsOiM4YTQxODI7ZmlsbC1vcGFjaXR5OjE7ZmlsbC1ydWxlOm5vbnplcm87c3Ryb2tlOm5vbmUiIC8+PHBhdGgKICAgICAgICAgICAgIGQ9Im0gMjk4OC4xOCw4MDAuMjU0IC02My4yNiwwIDAsMTA0LjUyNyAxNjUuMDUsMCAwLC03My4zNTUgYyAzMS4xOCw1MS4zNDcgNzguODYsODUuMjc3IDE0MS4yMSw4NS4yNzcgNjcuODUsMCAxMjQuNzEsLTQxLjI1OCAxNTIuMjEsLTEwMi42OTkgMjYuNiw2Mi4zNTEgOTIuNjIsMTAyLjY5OSAxNjAuNDcsMTAyLjY5OSA1My4xOSwwIDEwNS40NiwtMjIgMTQxLjIxLC02Mi4zNTEgMzguNTIsLTQ0LjkzOCAzOC41MiwtOTMuNTMyIDM4LjUyLC0xNDkuNDU3IGwgMCwtMTg1LjIzOSA2My4yNywwIDAsLTEwNC41MjcgLTIzOC40MiwwIDAsMTA0LjUyNyA2My4yOCwwIDAsMTU3LjcxNSBjIDAsMzIuMTAyIDAsNjAuNTI3IC0xNC42Nyw4OC45NTcgLTE4LjM0LDI2LjU4MiAtNDguNjEsNDAuMzQ0IC03OS43Nyw0MC4zNDQgLTMwLjI2LDAgLTYzLjI4LC0xMi44NDQgLTgyLjUzLC0zNi42NzIgLTIyLjkzLC0yOS4zNTUgLTIyLjkzLC01Ni44NjMgLTIyLjkzLC05Mi42MjkgbCAwLC0xNTcuNzE1IDYzLjI3LDAgMCwtMTA0LjUyNyAtMjM4LjQxLDAgMCwxMDQuNTI3IDYzLjI4LDAgMCwxNTAuMzgzIGMgMCwyOS4zNDggMCw2Ni4wMjMgLTE0LjY3LDkxLjY5OSAtMTUuNTksMjkuMzM2IC00Ny42OSw0NC45MzQgLTgwLjcsNDQuOTM0IC0zMS4xOCwwIC01Ny43NywtMTEuMDA4IC03Ny45NCwtMzUuNzc0IC0yNC43NywtMzAuMjUzIC0yNi42LC02Mi4zNDMgLTI2LjYsLTk5Ljk0MSBsIDAsLTE1MS4zMDEgNjMuMjcsMCAwLC0xMDQuNTI3IC0yMzguNCwwIDAsMTA0LjUyNyA2My4yNiwwIDAsMjgwLjU5OCIKICAgICAgICAgICAgIGlua3NjYXBlOmNvbm5lY3Rvci1jdXJ2YXR1cmU9IjAiCiAgICAgICAgICAgICBpZD0icGF0aDI4IgogICAgICAgICAgICAgc3R5bGU9ImZpbGw6IzhhNDE4MjtmaWxsLW9wYWNpdHk6MTtmaWxsLXJ1bGU6bm9uemVybztzdHJva2U6bm9uZSIgLz48cGF0aAogICAgICAgICAgICAgZD0ibSAzOTk4LjY2LDk1MS41NDcgLTExMS44NywwIDAsMTE4LjI5MyAxMTEuODcsMCAwLC0xMTguMjkzIHogbSAwLC00MzEuODkxIDYzLjI3LDAgMCwtMTA0LjUyNyAtMjM5LjMzLDAgMCwxMDQuNTI3IDY0LjE5LDAgMCwyODAuNTk4IC02My4yNywwIDAsMTA0LjUyNyAxNzUuMTQsMCAwLC0zODUuMTI1IgogICAgICAgICAgICAgaW5rc2NhcGU6Y29ubmVjdG9yLWN1cnZhdHVyZT0iMCIKICAgICAgICAgICAgIGlkPSJwYXRoMzAiCiAgICAgICAgICAgICBzdHlsZT0iZmlsbDojOGE0MTgyO2ZpbGwtb3BhY2l0eToxO2ZpbGwtcnVsZTpub256ZXJvO3N0cm9rZTpub25lIiAvPjxwYXRoCiAgICAgICAgICAgICBkPSJtIDQxNTkuMTIsODAwLjI1NCAtNjMuMjcsMCAwLDEwNC41MjcgMTc1LjE0LDAgMCwtNjkuNjg3IGMgMjkuMzUsNTQuMTAxIDg0LjM2LDgwLjY5OSAxNDQuODcsODAuNjk5IDUzLjE5LDAgMTA1LjQ1LC0yMi4wMTYgMTQxLjIyLC02MC41MjcgNDAuMzQsLTQ0LjkzNCA0MS4yNiwtODguMDMyIDQxLjI2LC0xNDMuOTU3IGwgMCwtMTkxLjY1MyA2My4yNywwIDAsLTEwNC41MjcgLTIzOC40LDAgMCwxMDQuNTI3IDYzLjI2LDAgMCwxNTguNjM3IGMgMCwzMC4yNjIgMCw2MS40MzQgLTE5LjI2LDg4LjAzNSAtMjAuMTcsMjYuNTgyIC01My4xOCwzOS40MTQgLTg2LjE5LDM5LjQxNCAtMzMuOTMsMCAtNjguNzcsLTEzLjc1IC04OC45NCwtNDEuMjUgLTIxLjA5LC0yNy41IC0yMS4wOSwtNjkuNjg3IC0yMS4wOSwtMTAyLjcwNyBsIDAsLTE0Mi4xMjkgNjMuMjYsMCAwLC0xMDQuNTI3IC0yMzguNCwwIDAsMTA0LjUyNyA2My4yNywwIDAsMjgwLjU5OCIKICAgICAgICAgICAgIGlua3NjYXBlOmNvbm5lY3Rvci1jdXJ2YXR1cmU9IjAiCiAgICAgICAgICAgICBpZD0icGF0aDMyIgogICAgICAgICAgICAgc3R5bGU9ImZpbGw6IzhhNDE4MjtmaWxsLW9wYWNpdHk6MTtmaWxsLXJ1bGU6bm9uemVybztzdHJva2U6bm9uZSIgLz48cGF0aAogICAgICAgICAgICAgZD0ibSA1MDgyLjQ4LDcwMy45NjUgYyAtMTkuMjQsNzAuNjA1IC04MS42LDExNS41NDcgLTE1NC4wNCwxMTUuNTQ3IC02Ni4wNCwwIC0xMjkuMywtNTEuMzQ4IC0xNDMuMDUsLTExNS41NDcgbCAyOTcuMDksMCB6IG0gODUuMjcsLTE0NC44ODMgYyAtMzguNTEsLTkzLjUyMyAtMTI5LjI3LC0xNTYuNzkzIC0yMzEuMDUsLTE1Ni43OTMgLTE0My4wNywwIC0yNTcuNjgsMTExLjg3MSAtMjU3LjY4LDI1NS44MzYgMCwxNDQuODgzIDEwOS4xMiwyNjEuMzI4IDI1NC45MSwyNjEuMzI4IDY3Ljg3LDAgMTM1LjcyLC0zMC4yNTggMTgzLjM5LC03OC44NjMgNDguNjIsLTUxLjM0NCA2OC43OSwtMTEzLjY5NSA2OC43OSwtMTgzLjM4MyBsIC0zLjY3LC0zOS40MzQgLTM5Ni4xMywwIGMgMTQuNjcsLTY3Ljg2MyA3Ny4wMywtMTE3LjM2MyAxNDYuNzIsLTExNy4zNjMgNDguNTksMCA5MC43NiwxOC4zMjggMTE4LjI4LDU4LjY3MiBsIDExNi40NCwwIgogICAgICAgICAgICAgaW5rc2NhcGU6Y29ubmVjdG9yLWN1cnZhdHVyZT0iMCIKICAgICAgICAgICAgIGlkPSJwYXRoMzQiCiAgICAgICAgICAgICBzdHlsZT0iZmlsbDojOGE0MTgyO2ZpbGwtb3BhY2l0eToxO2ZpbGwtcnVsZTpub256ZXJvO3N0cm9rZTpub25lIiAvPjxwYXRoCiAgICAgICAgICAgICBkPSJtIDY5MC44OTUsODUwLjcwMyA5MC43NSwwIDIyLjU0MywzMS4wMzUgMCwyNDMuMTIyIC0xMzUuODI5LDAgMCwtMjQzLjE0MSAyMi41MzYsLTMxLjAxNiIKICAgICAgICAgICAgIGlua3NjYXBlOmNvbm5lY3Rvci1jdXJ2YXR1cmU9IjAiCiAgICAgICAgICAgICBpZD0icGF0aDM2IgogICAgICAgICAgICAgc3R5bGU9ImZpbGw6IzhhNDE4MjtmaWxsLW9wYWNpdHk6MTtmaWxsLXJ1bGU6bm9uemVybztzdHJva2U6bm9uZSIgLz48cGF0aAogICAgICAgICAgICAgZD0ibSA2MzIuMzk1LDc0Mi4yNTggMjguMDM5LDg2LjMwNCAtMjIuNTUxLDMxLjA0IC0yMzEuMjIzLDc1LjEyOCAtNDEuOTc2LC0xMjkuMTgzIDIzMS4yNTcsLTc1LjEzNyAzNi40NTQsMTEuODQ4IgogICAgICAgICAgICAgaW5rc2NhcGU6Y29ubmVjdG9yLWN1cnZhdHVyZT0iMCIKICAgICAgICAgICAgIGlkPSJwYXRoMzgiCiAgICAgICAgICAgICBzdHlsZT0iZmlsbDojOGE0MTgyO2ZpbGwtb3BhY2l0eToxO2ZpbGwtcnVsZTpub256ZXJvO3N0cm9rZTpub25lIiAvPjxwYXRoCiAgICAgICAgICAgICBkPSJtIDcxNy40NDksNjUzLjEwNSAtNzMuNDEsNTMuMzYgLTM2LjQ4OCwtMTEuODc1IC0xNDIuOTAzLC0xOTYuNjkyIDEwOS44ODMsLTc5LjgyOCAxNDIuOTE4LDE5Ni43MDMgMCwzOC4zMzIiCiAgICAgICAgICAgICBpbmtzY2FwZTpjb25uZWN0b3ItY3VydmF0dXJlPSIwIgogICAgICAgICAgICAgaWQ9InBhdGg0MCIKICAgICAgICAgICAgIHN0eWxlPSJmaWxsOiM4YTQxODI7ZmlsbC1vcGFjaXR5OjE7ZmlsbC1ydWxlOm5vbnplcm87c3Ryb2tlOm5vbmUiIC8+PHBhdGgKICAgICAgICAgICAgIGQ9Im0gODI4LjUyLDcwNi40NjUgLTczLjQyNiwtNTMuMzQgMC4wMTEsLTM4LjM1OSBMIDg5OC4wMDQsNDE4LjA3IDEwMDcuOSw0OTcuODk4IDg2NC45NzMsNjk0LjYwOSA4MjguNTIsNzA2LjQ2NSIKICAgICAgICAgICAgIGlua3NjYXBlOmNvbm5lY3Rvci1jdXJ2YXR1cmU9IjAiCiAgICAgICAgICAgICBpZD0icGF0aDQyIgogICAgICAgICAgICAgc3R5bGU9ImZpbGw6IzhhNDE4MjtmaWxsLW9wYWNpdHk6MTtmaWxsLXJ1bGU6bm9uemVybztzdHJva2U6bm9uZSIgLz48cGF0aAogICAgICAgICAgICAgZD0ibSA4MTIuMDg2LDgyOC41ODYgMjguMDU1LC04Ni4zMiAzNi40ODQsLTExLjgzNiAyMzEuMjI1LDc1LjExNyAtNDEuOTcsMTI5LjE4MyAtMjMxLjIzOSwtNzUuMTQgLTIyLjU1NSwtMzEuMDA0IgogICAgICAgICAgICAgaW5rc2NhcGU6Y29ubmVjdG9yLWN1cnZhdHVyZT0iMCIKICAgICAgICAgICAgIGlkPSJwYXRoNDQiCiAgICAgICAgICAgICBzdHlsZT0iZmlsbDojOGE0MTgyO2ZpbGwtb3BhY2l0eToxO2ZpbGwtcnVsZTpub256ZXJvO3N0cm9rZTpub25lIiAvPjxwYXRoCiAgICAgICAgICAgICBkPSJtIDczNi4zMDEsMTMzNS44OCBjIC0zMjMuMDQ3LDAgLTU4NS44NzUsLTI2Mi43OCAtNTg1Ljg3NSwtNTg1Ljc4MiAwLC0zMjMuMTE4IDI2Mi44MjgsLTU4NS45NzcgNTg1Ljg3NSwtNTg1Ljk3NyAzMjMuMDE5LDAgNTg1LjgwOSwyNjIuODU5IDU4NS44MDksNTg1Ljk3NyAwLDMyMy4wMDIgLTI2Mi43OSw1ODUuNzgyIC01ODUuODA5LDU4NS43ODIgbCAwLDAgeiBtIDAsLTExOC42MSBjIDI1Ny45NzIsMCA0NjcuMTg5LC0yMDkuMTMgNDY3LjE4OSwtNDY3LjE3MiAwLC0yNTguMTI5IC0yMDkuMjE3LC00NjcuMzQ4IC00NjcuMTg5LC00NjcuMzQ4IC0yNTguMDc0LDAgLTQ2Ny4yNTQsMjA5LjIxOSAtNDY3LjI1NCw0NjcuMzQ4IDAsMjU4LjA0MiAyMDkuMTgsNDY3LjE3MiA0NjcuMjU0LDQ2Ny4xNzIiCiAgICAgICAgICAgICBpbmtzY2FwZTpjb25uZWN0b3ItY3VydmF0dXJlPSIwIgogICAgICAgICAgICAgaWQ9InBhdGg0NiIKICAgICAgICAgICAgIHN0eWxlPSJmaWxsOiM4YTQxODI7ZmlsbC1vcGFjaXR5OjE7ZmlsbC1ydWxlOm5vbnplcm87c3Ryb2tlOm5vbmUiIC8+PHBhdGgKICAgICAgICAgICAgIGQ9Im0gMTA5MS4xMyw2MTkuODgzIC0xNzUuNzcxLDU3LjEyMSAxMS42MjksMzUuODA4IDE3NS43NjIsLTU3LjEyMSAtMTEuNjIsLTM1LjgwOCIKICAgICAgICAgICAgIGlua3NjYXBlOmNvbm5lY3Rvci1jdXJ2YXR1cmU9IjAiCiAgICAgICAgICAgICBpZD0icGF0aDQ4IgogICAgICAgICAgICAgc3R5bGU9ImZpbGw6IzhhNDE4MjtmaWxsLW9wYWNpdHk6MTtmaWxsLXJ1bGU6bm9uemVybztzdHJva2U6bm9uZSIgLz48cGF0aAogICAgICAgICAgICAgZD0iTSA4NjYuOTU3LDkwMi4wNzQgODM2LjUsOTI0LjE5OSA5NDUuMTIxLDEwNzMuNzMgOTc1LjU4NiwxMDUxLjYxIDg2Ni45NTcsOTAyLjA3NCIKICAgICAgICAgICAgIGlua3NjYXBlOmNvbm5lY3Rvci1jdXJ2YXR1cmU9IjAiCiAgICAgICAgICAgICBpZD0icGF0aDUwIgogICAgICAgICAgICAgc3R5bGU9ImZpbGw6IzhhNDE4MjtmaWxsLW9wYWNpdHk6MTtmaWxsLXJ1bGU6bm9uemVybztzdHJva2U6bm9uZSIgLz48cGF0aAogICAgICAgICAgICAgZD0iTSA2MDcuNDY1LDkwMy40NDUgNDk4Ljg1NSwxMDUyLjk3IDUyOS4zMiwxMDc1LjEgNjM3LjkzLDkyNS41NjYgNjA3LjQ2NSw5MDMuNDQ1IgogICAgICAgICAgICAgaW5rc2NhcGU6Y29ubmVjdG9yLWN1cnZhdHVyZT0iMCIKICAgICAgICAgICAgIGlkPSJwYXRoNTIiCiAgICAgICAgICAgICBzdHlsZT0iZmlsbDojOGE0MTgyO2ZpbGwtb3BhY2l0eToxO2ZpbGwtcnVsZTpub256ZXJvO3N0cm9rZTpub25lIiAvPjxwYXRoCiAgICAgICAgICAgICBkPSJtIDM4MC42ODgsNjIyLjEyOSAtMTEuNjI2LDM1LjgwMSAxNzUuNzU4LDU3LjA5IDExLjYyMSwtMzUuODAxIC0xNzUuNzUzLC01Ny4wOSIKICAgICAgICAgICAgIGlua3NjYXBlOmNvbm5lY3Rvci1jdXJ2YXR1cmU9IjAiCiAgICAgICAgICAgICBpZD0icGF0aDU0IgogICAgICAgICAgICAgc3R5bGU9ImZpbGw6IzhhNDE4MjtmaWxsLW9wYWNpdHk6MTtmaWxsLXJ1bGU6bm9uemVybztzdHJva2U6bm9uZSIgLz48cGF0aAogICAgICAgICAgICAgZD0ibSA3MTYuMjg5LDM3Ni41OSAzNy42NDA2LDAgMCwxODQuODE2IC0zNy42NDA2LDAgMCwtMTg0LjgxNiB6IgogICAgICAgICAgICAgaW5rc2NhcGU6Y29ubmVjdG9yLWN1cnZhdHVyZT0iMCIKICAgICAgICAgICAgIGlkPSJwYXRoNTYiCiAgICAgICAgICAgICBzdHlsZT0iZmlsbDojOGE0MTgyO2ZpbGwtb3BhY2l0eToxO2ZpbGwtcnVsZTpub256ZXJvO3N0cm9rZTpub25lIiAvPjwvZz48L2c+PC9nPjwvZz48L3N2Zz4=') no-repeat, none; -moz-background-size: 100%; -o-background-size: 100%; -webkit-background-size: 100%; background-size: 100%; display: block; float: left; width: 90px; height: 25px; } 10 | .jasmine_html-reporter .jasmine-banner .jasmine-version { margin-left: 14px; position: relative; top: 6px; } 11 | .jasmine_html-reporter #jasmine_content { position: fixed; right: 100%; } 12 | .jasmine_html-reporter .jasmine-version { color: #aaa; } 13 | .jasmine_html-reporter .jasmine-banner { margin-top: 14px; } 14 | .jasmine_html-reporter .jasmine-duration { color: #fff; float: right; line-height: 28px; padding-right: 9px; } 15 | .jasmine_html-reporter .jasmine-symbol-summary { overflow: hidden; *zoom: 1; margin: 14px 0; } 16 | .jasmine_html-reporter .jasmine-symbol-summary li { display: inline-block; height: 10px; width: 14px; font-size: 16px; } 17 | .jasmine_html-reporter .jasmine-symbol-summary li.jasmine-passed { font-size: 14px; } 18 | .jasmine_html-reporter .jasmine-symbol-summary li.jasmine-passed:before { color: #007069; content: "\02022"; } 19 | .jasmine_html-reporter .jasmine-symbol-summary li.jasmine-failed { line-height: 9px; } 20 | .jasmine_html-reporter .jasmine-symbol-summary li.jasmine-failed:before { color: #ca3a11; content: "\d7"; font-weight: bold; margin-left: -1px; } 21 | .jasmine_html-reporter .jasmine-symbol-summary li.jasmine-disabled { font-size: 14px; } 22 | .jasmine_html-reporter .jasmine-symbol-summary li.jasmine-disabled:before { color: #bababa; content: "\02022"; } 23 | .jasmine_html-reporter .jasmine-symbol-summary li.jasmine-pending { line-height: 17px; } 24 | .jasmine_html-reporter .jasmine-symbol-summary li.jasmine-pending:before { color: #ba9d37; content: "*"; } 25 | .jasmine_html-reporter .jasmine-symbol-summary li.jasmine-empty { font-size: 14px; } 26 | .jasmine_html-reporter .jasmine-symbol-summary li.jasmine-empty:before { color: #ba9d37; content: "\02022"; } 27 | .jasmine_html-reporter .jasmine-run-options { float: right; margin-right: 5px; border: 1px solid #8a4182; color: #8a4182; position: relative; line-height: 20px; } 28 | .jasmine_html-reporter .jasmine-run-options .jasmine-trigger { cursor: pointer; padding: 8px 16px; } 29 | .jasmine_html-reporter .jasmine-run-options .jasmine-payload { position: absolute; display: none; right: -1px; border: 1px solid #8a4182; background-color: #eee; white-space: nowrap; padding: 4px 8px; } 30 | .jasmine_html-reporter .jasmine-run-options .jasmine-payload.jasmine-open { display: block; } 31 | .jasmine_html-reporter .jasmine-bar { line-height: 28px; font-size: 14px; display: block; color: #eee; } 32 | .jasmine_html-reporter .jasmine-bar.jasmine-failed { background-color: #ca3a11; } 33 | .jasmine_html-reporter .jasmine-bar.jasmine-passed { background-color: #007069; } 34 | .jasmine_html-reporter .jasmine-bar.jasmine-skipped { background-color: #bababa; } 35 | .jasmine_html-reporter .jasmine-bar.jasmine-errored { background-color: #ca3a11; } 36 | .jasmine_html-reporter .jasmine-bar.jasmine-menu { background-color: #fff; color: #aaa; } 37 | .jasmine_html-reporter .jasmine-bar.jasmine-menu a { color: #333; } 38 | .jasmine_html-reporter .jasmine-bar a { color: white; } 39 | .jasmine_html-reporter.jasmine-spec-list .jasmine-bar.jasmine-menu.jasmine-failure-list, .jasmine_html-reporter.jasmine-spec-list .jasmine-results .jasmine-failures { display: none; } 40 | .jasmine_html-reporter.jasmine-failure-list .jasmine-bar.jasmine-menu.jasmine-spec-list, .jasmine_html-reporter.jasmine-failure-list .jasmine-summary { display: none; } 41 | .jasmine_html-reporter .jasmine-results { margin-top: 14px; } 42 | .jasmine_html-reporter .jasmine-summary { margin-top: 14px; } 43 | .jasmine_html-reporter .jasmine-summary ul { list-style-type: none; margin-left: 14px; padding-top: 0; padding-left: 0; } 44 | .jasmine_html-reporter .jasmine-summary ul.jasmine-suite { margin-top: 7px; margin-bottom: 7px; } 45 | .jasmine_html-reporter .jasmine-summary li.jasmine-passed a { color: #007069; } 46 | .jasmine_html-reporter .jasmine-summary li.jasmine-failed a { color: #ca3a11; } 47 | .jasmine_html-reporter .jasmine-summary li.jasmine-empty a { color: #ba9d37; } 48 | .jasmine_html-reporter .jasmine-summary li.jasmine-pending a { color: #ba9d37; } 49 | .jasmine_html-reporter .jasmine-summary li.jasmine-disabled a { color: #bababa; } 50 | .jasmine_html-reporter .jasmine-description + .jasmine-suite { margin-top: 0; } 51 | .jasmine_html-reporter .jasmine-suite { margin-top: 14px; } 52 | .jasmine_html-reporter .jasmine-suite a { color: #333; } 53 | .jasmine_html-reporter .jasmine-failures .jasmine-spec-detail { margin-bottom: 28px; } 54 | .jasmine_html-reporter .jasmine-failures .jasmine-spec-detail .jasmine-description { background-color: #ca3a11; } 55 | .jasmine_html-reporter .jasmine-failures .jasmine-spec-detail .jasmine-description a { color: white; } 56 | .jasmine_html-reporter .jasmine-result-message { padding-top: 14px; color: #333; white-space: pre; } 57 | .jasmine_html-reporter .jasmine-result-message span.jasmine-result { display: block; } 58 | .jasmine_html-reporter .jasmine-stack-trace { margin: 5px 0 0 0; max-height: 224px; overflow: auto; line-height: 18px; color: #666; border: 1px solid #ddd; background: white; white-space: pre; } 59 | -------------------------------------------------------------------------------- /lib/jasmine-2.4.1/mock-ajax.js: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Jasmine-Ajax - v3.2.0: a set of helpers for testing AJAX requests under the Jasmine 4 | BDD framework for JavaScript. 5 | 6 | http://github.com/jasmine/jasmine-ajax 7 | 8 | Jasmine Home page: http://jasmine.github.io/ 9 | 10 | Copyright (c) 2008-2015 Pivotal Labs 11 | 12 | Permission is hereby granted, free of charge, to any person obtaining 13 | a copy of this software and associated documentation files (the 14 | "Software"), to deal in the Software without restriction, including 15 | without limitation the rights to use, copy, modify, merge, publish, 16 | distribute, sublicense, and/or sell copies of the Software, and to 17 | permit persons to whom the Software is furnished to do so, subject to 18 | the following conditions: 19 | 20 | The above copyright notice and this permission notice shall be 21 | included in all copies or substantial portions of the Software. 22 | 23 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 24 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 25 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 26 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 27 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 28 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 29 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 30 | 31 | */ 32 | 33 | //Module wrapper to support both browser and CommonJS environment 34 | (function (root, factory) { 35 | if (typeof exports === 'object' && typeof exports.nodeName !== 'string') { 36 | // CommonJS 37 | var jasmineRequire = require('jasmine-core'); 38 | module.exports = factory(root, function() { 39 | return jasmineRequire; 40 | }); 41 | } else { 42 | // Browser globals 43 | window.MockAjax = factory(root, getJasmineRequireObj); 44 | } 45 | }(typeof window !== 'undefined' ? window : global, function (global, getJasmineRequireObj) { 46 | 47 | // 48 | getJasmineRequireObj().ajax = function(jRequire) { 49 | var $ajax = {}; 50 | 51 | $ajax.RequestStub = jRequire.AjaxRequestStub(); 52 | $ajax.RequestTracker = jRequire.AjaxRequestTracker(); 53 | $ajax.StubTracker = jRequire.AjaxStubTracker(); 54 | $ajax.ParamParser = jRequire.AjaxParamParser(); 55 | $ajax.event = jRequire.AjaxEvent(); 56 | $ajax.eventBus = jRequire.AjaxEventBus($ajax.event); 57 | $ajax.fakeRequest = jRequire.AjaxFakeRequest($ajax.eventBus); 58 | $ajax.MockAjax = jRequire.MockAjax($ajax); 59 | 60 | return $ajax.MockAjax; 61 | }; 62 | 63 | getJasmineRequireObj().AjaxEvent = function() { 64 | function now() { 65 | return new Date().getTime(); 66 | } 67 | 68 | function noop() { 69 | } 70 | 71 | // Event object 72 | // https://dom.spec.whatwg.org/#concept-event 73 | function XMLHttpRequestEvent(xhr, type) { 74 | this.type = type; 75 | this.bubbles = false; 76 | this.cancelable = false; 77 | this.timeStamp = now(); 78 | 79 | this.isTrusted = false; 80 | this.defaultPrevented = false; 81 | 82 | // Event phase should be "AT_TARGET" 83 | // https://dom.spec.whatwg.org/#dom-event-at_target 84 | this.eventPhase = 2; 85 | 86 | this.target = xhr; 87 | this.currentTarget = xhr; 88 | } 89 | 90 | XMLHttpRequestEvent.prototype.preventDefault = noop; 91 | XMLHttpRequestEvent.prototype.stopPropagation = noop; 92 | XMLHttpRequestEvent.prototype.stopImmediatePropagation = noop; 93 | 94 | function XMLHttpRequestProgressEvent() { 95 | XMLHttpRequestEvent.apply(this, arguments); 96 | 97 | this.lengthComputable = false; 98 | this.loaded = 0; 99 | this.total = 0; 100 | } 101 | 102 | // Extend prototype 103 | XMLHttpRequestProgressEvent.prototype = XMLHttpRequestEvent.prototype; 104 | 105 | return { 106 | event: function(xhr, type) { 107 | return new XMLHttpRequestEvent(xhr, type); 108 | }, 109 | 110 | progressEvent: function(xhr, type) { 111 | return new XMLHttpRequestProgressEvent(xhr, type); 112 | } 113 | }; 114 | }; 115 | getJasmineRequireObj().AjaxEventBus = function(eventFactory) { 116 | function EventBus(source) { 117 | this.eventList = {}; 118 | this.source = source; 119 | } 120 | 121 | function ensureEvent(eventList, name) { 122 | eventList[name] = eventList[name] || []; 123 | return eventList[name]; 124 | } 125 | 126 | function findIndex(list, thing) { 127 | if (list.indexOf) { 128 | return list.indexOf(thing); 129 | } 130 | 131 | for(var i = 0; i < list.length; i++) { 132 | if (thing === list[i]) { 133 | return i; 134 | } 135 | } 136 | 137 | return -1; 138 | } 139 | 140 | EventBus.prototype.addEventListener = function(event, callback) { 141 | ensureEvent(this.eventList, event).push(callback); 142 | }; 143 | 144 | EventBus.prototype.removeEventListener = function(event, callback) { 145 | var index = findIndex(this.eventList[event], callback); 146 | 147 | if (index >= 0) { 148 | this.eventList[event].splice(index, 1); 149 | } 150 | }; 151 | 152 | EventBus.prototype.trigger = function(event) { 153 | var evt; 154 | 155 | // Event 'readystatechange' is should be a simple event. 156 | // Others are progress event. 157 | // https://xhr.spec.whatwg.org/#events 158 | if (event === 'readystatechange') { 159 | evt = eventFactory.event(this.source, event); 160 | } else { 161 | evt = eventFactory.progressEvent(this.source, event); 162 | } 163 | 164 | var eventListeners = this.eventList[event]; 165 | 166 | if (eventListeners) { 167 | for (var i = 0; i < eventListeners.length; i++) { 168 | eventListeners[i].call(this.source, evt); 169 | } 170 | } 171 | }; 172 | 173 | return function(source) { 174 | return new EventBus(source); 175 | }; 176 | }; 177 | 178 | getJasmineRequireObj().AjaxFakeRequest = function(eventBusFactory) { 179 | function extend(destination, source, propertiesToSkip) { 180 | propertiesToSkip = propertiesToSkip || []; 181 | for (var property in source) { 182 | if (!arrayContains(propertiesToSkip, property)) { 183 | destination[property] = source[property]; 184 | } 185 | } 186 | return destination; 187 | } 188 | 189 | function arrayContains(arr, item) { 190 | for (var i = 0; i < arr.length; i++) { 191 | if (arr[i] === item) { 192 | return true; 193 | } 194 | } 195 | return false; 196 | } 197 | 198 | function wrapProgressEvent(xhr, eventName) { 199 | return function() { 200 | if (xhr[eventName]) { 201 | xhr[eventName].apply(xhr, arguments); 202 | } 203 | }; 204 | } 205 | 206 | function initializeEvents(xhr) { 207 | xhr.eventBus.addEventListener('readystatechange', wrapProgressEvent(xhr, 'onreadystatechange')); 208 | xhr.eventBus.addEventListener('loadstart', wrapProgressEvent(xhr, 'onloadstart')); 209 | xhr.eventBus.addEventListener('load', wrapProgressEvent(xhr, 'onload')); 210 | xhr.eventBus.addEventListener('loadend', wrapProgressEvent(xhr, 'onloadend')); 211 | xhr.eventBus.addEventListener('progress', wrapProgressEvent(xhr, 'onprogress')); 212 | xhr.eventBus.addEventListener('error', wrapProgressEvent(xhr, 'onerror')); 213 | xhr.eventBus.addEventListener('abort', wrapProgressEvent(xhr, 'onabort')); 214 | xhr.eventBus.addEventListener('timeout', wrapProgressEvent(xhr, 'ontimeout')); 215 | } 216 | 217 | function unconvertibleResponseTypeMessage(type) { 218 | var msg = [ 219 | "Can't build XHR.response for XHR.responseType of '", 220 | type, 221 | "'.", 222 | "XHR.response must be explicitly stubbed" 223 | ]; 224 | return msg.join(' '); 225 | } 226 | 227 | function fakeRequest(global, requestTracker, stubTracker, paramParser) { 228 | function FakeXMLHttpRequest() { 229 | requestTracker.track(this); 230 | this.eventBus = eventBusFactory(this); 231 | initializeEvents(this); 232 | this.requestHeaders = {}; 233 | this.overriddenMimeType = null; 234 | } 235 | 236 | function findHeader(name, headers) { 237 | name = name.toLowerCase(); 238 | for (var header in headers) { 239 | if (header.toLowerCase() === name) { 240 | return headers[header]; 241 | } 242 | } 243 | } 244 | 245 | function normalizeHeaders(rawHeaders, contentType) { 246 | var headers = []; 247 | 248 | if (rawHeaders) { 249 | if (rawHeaders instanceof Array) { 250 | headers = rawHeaders; 251 | } else { 252 | for (var headerName in rawHeaders) { 253 | if (rawHeaders.hasOwnProperty(headerName)) { 254 | headers.push({ name: headerName, value: rawHeaders[headerName] }); 255 | } 256 | } 257 | } 258 | } else { 259 | headers.push({ name: "Content-Type", value: contentType || "application/json" }); 260 | } 261 | 262 | return headers; 263 | } 264 | 265 | function parseXml(xmlText, contentType) { 266 | if (global.DOMParser) { 267 | return (new global.DOMParser()).parseFromString(xmlText, 'text/xml'); 268 | } else { 269 | var xml = new global.ActiveXObject("Microsoft.XMLDOM"); 270 | xml.async = "false"; 271 | xml.loadXML(xmlText); 272 | return xml; 273 | } 274 | } 275 | 276 | var xmlParsables = ['text/xml', 'application/xml']; 277 | 278 | function getResponseXml(responseText, contentType) { 279 | if (arrayContains(xmlParsables, contentType.toLowerCase())) { 280 | return parseXml(responseText, contentType); 281 | } else if (contentType.match(/\+xml$/)) { 282 | return parseXml(responseText, 'text/xml'); 283 | } 284 | return null; 285 | } 286 | 287 | var iePropertiesThatCannotBeCopied = ['responseBody', 'responseText', 'responseXML', 'status', 'statusText', 'responseTimeout', 'responseURL']; 288 | extend(FakeXMLHttpRequest.prototype, new global.XMLHttpRequest(), iePropertiesThatCannotBeCopied); 289 | extend(FakeXMLHttpRequest.prototype, { 290 | open: function() { 291 | this.method = arguments[0]; 292 | this.url = arguments[1]; 293 | this.username = arguments[3]; 294 | this.password = arguments[4]; 295 | this.readyState = 1; 296 | this.requestHeaders = {}; 297 | this.eventBus.trigger('readystatechange'); 298 | }, 299 | 300 | setRequestHeader: function(header, value) { 301 | if(this.requestHeaders.hasOwnProperty(header)) { 302 | this.requestHeaders[header] = [this.requestHeaders[header], value].join(', '); 303 | } else { 304 | this.requestHeaders[header] = value; 305 | } 306 | }, 307 | 308 | overrideMimeType: function(mime) { 309 | this.overriddenMimeType = mime; 310 | }, 311 | 312 | abort: function() { 313 | this.readyState = 0; 314 | this.status = 0; 315 | this.statusText = "abort"; 316 | this.eventBus.trigger('readystatechange'); 317 | this.eventBus.trigger('progress'); 318 | this.eventBus.trigger('abort'); 319 | this.eventBus.trigger('loadend'); 320 | }, 321 | 322 | readyState: 0, 323 | 324 | onloadstart: null, 325 | onprogress: null, 326 | onabort: null, 327 | onerror: null, 328 | onload: null, 329 | ontimeout: null, 330 | onloadend: null, 331 | onreadystatechange: null, 332 | 333 | addEventListener: function() { 334 | this.eventBus.addEventListener.apply(this.eventBus, arguments); 335 | }, 336 | 337 | removeEventListener: function(event, callback) { 338 | this.eventBus.removeEventListener.apply(this.eventBus, arguments); 339 | }, 340 | 341 | status: null, 342 | 343 | send: function(data) { 344 | this.params = data; 345 | this.eventBus.trigger('loadstart'); 346 | 347 | var stub = stubTracker.findStub(this.url, data, this.method); 348 | 349 | this.dispatchStub(stub); 350 | }, 351 | 352 | dispatchStub: function(stub) { 353 | if (stub) { 354 | if (stub.isReturn()) { 355 | this.respondWith(stub); 356 | } else if (stub.isError()) { 357 | this.responseError(); 358 | } else if (stub.isTimeout()) { 359 | this.responseTimeout(); 360 | } else if (stub.isCallFunction()) { 361 | this.responseCallFunction(stub); 362 | } 363 | } 364 | }, 365 | 366 | contentType: function() { 367 | return findHeader('content-type', this.requestHeaders); 368 | }, 369 | 370 | data: function() { 371 | if (!this.params) { 372 | return {}; 373 | } 374 | 375 | return paramParser.findParser(this).parse(this.params); 376 | }, 377 | 378 | getResponseHeader: function(name) { 379 | name = name.toLowerCase(); 380 | var resultHeader; 381 | for(var i = 0; i < this.responseHeaders.length; i++) { 382 | var header = this.responseHeaders[i]; 383 | if (name === header.name.toLowerCase()) { 384 | if (resultHeader) { 385 | resultHeader = [resultHeader, header.value].join(', '); 386 | } else { 387 | resultHeader = header.value; 388 | } 389 | } 390 | } 391 | return resultHeader; 392 | }, 393 | 394 | getAllResponseHeaders: function() { 395 | var responseHeaders = []; 396 | for (var i = 0; i < this.responseHeaders.length; i++) { 397 | responseHeaders.push(this.responseHeaders[i].name + ': ' + 398 | this.responseHeaders[i].value); 399 | } 400 | return responseHeaders.join('\r\n') + '\r\n'; 401 | }, 402 | 403 | responseText: null, 404 | response: null, 405 | responseType: null, 406 | responseURL: null, 407 | 408 | responseValue: function() { 409 | switch(this.responseType) { 410 | case null: 411 | case "": 412 | case "text": 413 | return this.readyState >= 3 ? this.responseText : ""; 414 | case "json": 415 | return JSON.parse(this.responseText); 416 | case "arraybuffer": 417 | throw unconvertibleResponseTypeMessage('arraybuffer'); 418 | case "blob": 419 | throw unconvertibleResponseTypeMessage('blob'); 420 | case "document": 421 | return this.responseXML; 422 | } 423 | }, 424 | 425 | 426 | respondWith: function(response) { 427 | if (this.readyState === 4) { 428 | throw new Error("FakeXMLHttpRequest already completed"); 429 | } 430 | 431 | this.status = response.status; 432 | this.statusText = response.statusText || ""; 433 | this.responseHeaders = normalizeHeaders(response.responseHeaders, response.contentType); 434 | this.readyState = 2; 435 | this.eventBus.trigger('readystatechange'); 436 | 437 | this.responseText = response.responseText || ""; 438 | this.responseType = response.responseType || ""; 439 | this.responseURL = response.responseURL || null; 440 | this.readyState = 4; 441 | this.responseXML = getResponseXml(response.responseText, this.getResponseHeader('content-type') || ''); 442 | if (this.responseXML) { 443 | this.responseType = 'document'; 444 | } 445 | 446 | if ('response' in response) { 447 | this.response = response.response; 448 | } else { 449 | this.response = this.responseValue(); 450 | } 451 | 452 | this.eventBus.trigger('readystatechange'); 453 | this.eventBus.trigger('progress'); 454 | this.eventBus.trigger('load'); 455 | this.eventBus.trigger('loadend'); 456 | }, 457 | 458 | responseTimeout: function() { 459 | if (this.readyState === 4) { 460 | throw new Error("FakeXMLHttpRequest already completed"); 461 | } 462 | this.readyState = 4; 463 | jasmine.clock().tick(30000); 464 | this.eventBus.trigger('readystatechange'); 465 | this.eventBus.trigger('progress'); 466 | this.eventBus.trigger('timeout'); 467 | this.eventBus.trigger('loadend'); 468 | }, 469 | 470 | responseError: function() { 471 | if (this.readyState === 4) { 472 | throw new Error("FakeXMLHttpRequest already completed"); 473 | } 474 | this.readyState = 4; 475 | this.eventBus.trigger('readystatechange'); 476 | this.eventBus.trigger('progress'); 477 | this.eventBus.trigger('error'); 478 | this.eventBus.trigger('loadend'); 479 | }, 480 | 481 | responseCallFunction: function(stub) { 482 | stub.action = undefined; 483 | stub.functionToCall(stub, this); 484 | this.dispatchStub(stub); 485 | } 486 | }); 487 | 488 | return FakeXMLHttpRequest; 489 | } 490 | 491 | return fakeRequest; 492 | }; 493 | 494 | getJasmineRequireObj().MockAjax = function($ajax) { 495 | function MockAjax(global) { 496 | var requestTracker = new $ajax.RequestTracker(), 497 | stubTracker = new $ajax.StubTracker(), 498 | paramParser = new $ajax.ParamParser(), 499 | realAjaxFunction = global.XMLHttpRequest, 500 | mockAjaxFunction = $ajax.fakeRequest(global, requestTracker, stubTracker, paramParser); 501 | 502 | this.install = function() { 503 | if (global.XMLHttpRequest === mockAjaxFunction) { 504 | throw "MockAjax is already installed."; 505 | } 506 | 507 | global.XMLHttpRequest = mockAjaxFunction; 508 | }; 509 | 510 | this.uninstall = function() { 511 | if (global.XMLHttpRequest !== mockAjaxFunction) { 512 | throw "MockAjax not installed."; 513 | } 514 | global.XMLHttpRequest = realAjaxFunction; 515 | 516 | this.stubs.reset(); 517 | this.requests.reset(); 518 | paramParser.reset(); 519 | }; 520 | 521 | this.stubRequest = function(url, data, method) { 522 | var stub = new $ajax.RequestStub(url, data, method); 523 | stubTracker.addStub(stub); 524 | return stub; 525 | }; 526 | 527 | this.withMock = function(closure) { 528 | this.install(); 529 | try { 530 | closure(); 531 | } finally { 532 | this.uninstall(); 533 | } 534 | }; 535 | 536 | this.addCustomParamParser = function(parser) { 537 | paramParser.add(parser); 538 | }; 539 | 540 | this.requests = requestTracker; 541 | this.stubs = stubTracker; 542 | } 543 | 544 | return MockAjax; 545 | }; 546 | 547 | getJasmineRequireObj().AjaxParamParser = function() { 548 | function ParamParser() { 549 | var defaults = [ 550 | { 551 | test: function(xhr) { 552 | return (/^application\/json/).test(xhr.contentType()); 553 | }, 554 | parse: function jsonParser(paramString) { 555 | return JSON.parse(paramString); 556 | } 557 | }, 558 | { 559 | test: function(xhr) { 560 | return true; 561 | }, 562 | parse: function naiveParser(paramString) { 563 | var data = {}; 564 | var params = paramString.split('&'); 565 | 566 | for (var i = 0; i < params.length; ++i) { 567 | var kv = params[i].replace(/\+/g, ' ').split('='); 568 | var key = decodeURIComponent(kv[0]); 569 | data[key] = data[key] || []; 570 | data[key].push(decodeURIComponent(kv[1])); 571 | } 572 | return data; 573 | } 574 | } 575 | ]; 576 | var paramParsers = []; 577 | 578 | this.add = function(parser) { 579 | paramParsers.unshift(parser); 580 | }; 581 | 582 | this.findParser = function(xhr) { 583 | for(var i in paramParsers) { 584 | var parser = paramParsers[i]; 585 | if (parser.test(xhr)) { 586 | return parser; 587 | } 588 | } 589 | }; 590 | 591 | this.reset = function() { 592 | paramParsers = []; 593 | for(var i in defaults) { 594 | paramParsers.push(defaults[i]); 595 | } 596 | }; 597 | 598 | this.reset(); 599 | } 600 | 601 | return ParamParser; 602 | }; 603 | 604 | getJasmineRequireObj().AjaxRequestStub = function() { 605 | var RETURN = 0, 606 | ERROR = 1, 607 | TIMEOUT = 2, 608 | CALL = 3; 609 | 610 | function RequestStub(url, stubData, method) { 611 | var normalizeQuery = function(query) { 612 | return query ? query.split('&').sort().join('&') : undefined; 613 | }; 614 | 615 | if (url instanceof RegExp) { 616 | this.url = url; 617 | this.query = undefined; 618 | } else { 619 | var split = url.split('?'); 620 | this.url = split[0]; 621 | this.query = split.length > 1 ? normalizeQuery(split[1]) : undefined; 622 | } 623 | 624 | this.data = (stubData instanceof RegExp) ? stubData : normalizeQuery(stubData); 625 | this.method = method; 626 | 627 | this.andReturn = function(options) { 628 | this.action = RETURN; 629 | this.status = options.status || 200; 630 | 631 | this.contentType = options.contentType; 632 | this.response = options.response; 633 | this.responseText = options.responseText; 634 | this.responseHeaders = options.responseHeaders; 635 | this.responseURL = options.responseURL; 636 | }; 637 | 638 | this.isReturn = function() { 639 | return this.action === RETURN; 640 | }; 641 | 642 | this.andError = function() { 643 | this.action = ERROR; 644 | }; 645 | 646 | this.isError = function() { 647 | return this.action === ERROR; 648 | }; 649 | 650 | this.andTimeout = function() { 651 | this.action = TIMEOUT; 652 | }; 653 | 654 | this.isTimeout = function() { 655 | return this.action === TIMEOUT; 656 | }; 657 | 658 | this.andCallFunction = function(functionToCall) { 659 | this.action = CALL; 660 | this.functionToCall = functionToCall; 661 | }; 662 | 663 | this.isCallFunction = function() { 664 | return this.action === CALL; 665 | }; 666 | 667 | this.matches = function(fullUrl, data, method) { 668 | var urlMatches = false; 669 | fullUrl = fullUrl.toString(); 670 | if (this.url instanceof RegExp) { 671 | urlMatches = this.url.test(fullUrl); 672 | } else { 673 | var urlSplit = fullUrl.split('?'), 674 | url = urlSplit[0], 675 | query = urlSplit[1]; 676 | urlMatches = this.url === url && this.query === normalizeQuery(query); 677 | } 678 | var dataMatches = false; 679 | if (this.data instanceof RegExp) { 680 | dataMatches = this.data.test(data); 681 | } else { 682 | dataMatches = !this.data || this.data === normalizeQuery(data); 683 | } 684 | return urlMatches && dataMatches && (!this.method || this.method === method); 685 | }; 686 | } 687 | 688 | return RequestStub; 689 | }; 690 | 691 | getJasmineRequireObj().AjaxRequestTracker = function() { 692 | function RequestTracker() { 693 | var requests = []; 694 | 695 | this.track = function(request) { 696 | requests.push(request); 697 | }; 698 | 699 | this.first = function() { 700 | return requests[0]; 701 | }; 702 | 703 | this.count = function() { 704 | return requests.length; 705 | }; 706 | 707 | this.reset = function() { 708 | requests = []; 709 | }; 710 | 711 | this.mostRecent = function() { 712 | return requests[requests.length - 1]; 713 | }; 714 | 715 | this.at = function(index) { 716 | return requests[index]; 717 | }; 718 | 719 | this.filter = function(url_to_match) { 720 | var matching_requests = []; 721 | 722 | for (var i = 0; i < requests.length; i++) { 723 | if (url_to_match instanceof RegExp && 724 | url_to_match.test(requests[i].url)) { 725 | matching_requests.push(requests[i]); 726 | } else if (url_to_match instanceof Function && 727 | url_to_match(requests[i])) { 728 | matching_requests.push(requests[i]); 729 | } else { 730 | if (requests[i].url === url_to_match) { 731 | matching_requests.push(requests[i]); 732 | } 733 | } 734 | } 735 | 736 | return matching_requests; 737 | }; 738 | } 739 | 740 | return RequestTracker; 741 | }; 742 | 743 | getJasmineRequireObj().AjaxStubTracker = function() { 744 | function StubTracker() { 745 | var stubs = []; 746 | 747 | this.addStub = function(stub) { 748 | stubs.push(stub); 749 | }; 750 | 751 | this.reset = function() { 752 | stubs = []; 753 | }; 754 | 755 | this.findStub = function(url, data, method) { 756 | for (var i = stubs.length - 1; i >= 0; i--) { 757 | var stub = stubs[i]; 758 | if (stub.matches(url, data, method)) { 759 | return stub; 760 | } 761 | } 762 | }; 763 | } 764 | 765 | return StubTracker; 766 | }; 767 | 768 | 769 | var jRequire = getJasmineRequireObj(); 770 | var MockAjax = jRequire.ajax(jRequire); 771 | jasmine.Ajax = new MockAjax(global); 772 | 773 | return MockAjax; 774 | })); 775 | -------------------------------------------------------------------------------- /lib/jasmine-2.4.1/jasmine-jquery.js: -------------------------------------------------------------------------------- 1 | /*! 2 | Jasmine-jQuery: a set of jQuery helpers for Jasmine tests. 3 | 4 | Version 2.1.1 5 | 6 | https://github.com/velesin/jasmine-jquery 7 | 8 | Copyright (c) 2010-2014 Wojciech Zawistowski, Travis Jeffery 9 | 10 | Permission is hereby granted, free of charge, to any person obtaining 11 | a copy of this software and associated documentation files (the 12 | "Software"), to deal in the Software without restriction, including 13 | without limitation the rights to use, copy, modify, merge, publish, 14 | distribute, sublicense, and/or sell copies of the Software, and to 15 | permit persons to whom the Software is furnished to do so, subject to 16 | the following conditions: 17 | 18 | The above copyright notice and this permission notice shall be 19 | included in all copies or substantial portions of the Software. 20 | 21 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 22 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 23 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 24 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 25 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 26 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 27 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 28 | */ 29 | 30 | (function (root, factory) { 31 | if (typeof module !== 'undefined' && module.exports) { 32 | factory(root, root.jasmine, require('jquery')); 33 | } else { 34 | factory(root, root.jasmine, root.jQuery); 35 | } 36 | }((function() {return this; })(), function (window, jasmine, $) { "use strict"; 37 | 38 | jasmine.spiedEventsKey = function (selector, eventName) { 39 | return [$(selector).selector, eventName].toString() 40 | } 41 | 42 | jasmine.getFixtures = function () { 43 | return jasmine.currentFixtures_ = jasmine.currentFixtures_ || new jasmine.Fixtures() 44 | } 45 | 46 | jasmine.getStyleFixtures = function () { 47 | return jasmine.currentStyleFixtures_ = jasmine.currentStyleFixtures_ || new jasmine.StyleFixtures() 48 | } 49 | 50 | jasmine.Fixtures = function () { 51 | this.containerId = 'jasmine-fixtures' 52 | this.fixturesCache_ = {} 53 | this.fixturesPath = 'spec/javascripts/fixtures' 54 | } 55 | 56 | jasmine.Fixtures.prototype.set = function (html) { 57 | this.cleanUp() 58 | return this.createContainer_(html) 59 | } 60 | 61 | jasmine.Fixtures.prototype.appendSet= function (html) { 62 | this.addToContainer_(html) 63 | } 64 | 65 | jasmine.Fixtures.prototype.preload = function () { 66 | this.read.apply(this, arguments) 67 | } 68 | 69 | jasmine.Fixtures.prototype.load = function () { 70 | this.cleanUp() 71 | this.createContainer_(this.read.apply(this, arguments)) 72 | } 73 | 74 | jasmine.Fixtures.prototype.appendLoad = function () { 75 | this.addToContainer_(this.read.apply(this, arguments)) 76 | } 77 | 78 | jasmine.Fixtures.prototype.read = function () { 79 | var htmlChunks = [] 80 | , fixtureUrls = arguments 81 | 82 | for(var urlCount = fixtureUrls.length, urlIndex = 0; urlIndex < urlCount; urlIndex++) { 83 | htmlChunks.push(this.getFixtureHtml_(fixtureUrls[urlIndex])) 84 | } 85 | 86 | return htmlChunks.join('') 87 | } 88 | 89 | jasmine.Fixtures.prototype.clearCache = function () { 90 | this.fixturesCache_ = {} 91 | } 92 | 93 | jasmine.Fixtures.prototype.cleanUp = function () { 94 | $('#' + this.containerId).remove() 95 | } 96 | 97 | jasmine.Fixtures.prototype.sandbox = function (attributes) { 98 | var attributesToSet = attributes || {} 99 | return $('
').attr(attributesToSet) 100 | } 101 | 102 | jasmine.Fixtures.prototype.createContainer_ = function (html) { 103 | var container = $('
') 104 | .attr('id', this.containerId) 105 | .html(html) 106 | 107 | $(document.body).append(container) 108 | return container 109 | } 110 | 111 | jasmine.Fixtures.prototype.addToContainer_ = function (html){ 112 | var container = $(document.body).find('#'+this.containerId).append(html) 113 | 114 | if (!container.length) { 115 | this.createContainer_(html) 116 | } 117 | } 118 | 119 | jasmine.Fixtures.prototype.getFixtureHtml_ = function (url) { 120 | if (typeof this.fixturesCache_[url] === 'undefined') { 121 | this.loadFixtureIntoCache_(url) 122 | } 123 | return this.fixturesCache_[url] 124 | } 125 | 126 | jasmine.Fixtures.prototype.loadFixtureIntoCache_ = function (relativeUrl) { 127 | var self = this 128 | , url = this.makeFixtureUrl_(relativeUrl) 129 | , htmlText = '' 130 | , request = $.ajax({ 131 | async: false, // must be synchronous to guarantee that no tests are run before fixture is loaded 132 | cache: false, 133 | url: url, 134 | dataType: 'html', 135 | success: function (data, status, $xhr) { 136 | htmlText = $xhr.responseText 137 | } 138 | }).fail(function ($xhr, status, err) { 139 | throw new Error('Fixture could not be loaded: ' + url + ' (status: ' + status + ', message: ' + err.message + ')') 140 | }) 141 | 142 | var scripts = $($.parseHTML(htmlText, true)).find('script[src]') || []; 143 | 144 | scripts.each(function(){ 145 | $.ajax({ 146 | async: false, // must be synchronous to guarantee that no tests are run before fixture is loaded 147 | cache: false, 148 | dataType: 'script', 149 | url: $(this).attr('src'), 150 | success: function (data, status, $xhr) { 151 | htmlText += '' 152 | }, 153 | error: function ($xhr, status, err) { 154 | throw new Error('Script could not be loaded: ' + url + ' (status: ' + status + ', message: ' + err.message + ')') 155 | } 156 | }); 157 | }) 158 | 159 | self.fixturesCache_[relativeUrl] = htmlText; 160 | } 161 | 162 | jasmine.Fixtures.prototype.makeFixtureUrl_ = function (relativeUrl){ 163 | return this.fixturesPath.match('/$') ? this.fixturesPath + relativeUrl : this.fixturesPath + '/' + relativeUrl 164 | } 165 | 166 | jasmine.Fixtures.prototype.proxyCallTo_ = function (methodName, passedArguments) { 167 | return this[methodName].apply(this, passedArguments) 168 | } 169 | 170 | 171 | jasmine.StyleFixtures = function () { 172 | this.fixturesCache_ = {} 173 | this.fixturesNodes_ = [] 174 | this.fixturesPath = 'spec/javascripts/fixtures' 175 | } 176 | 177 | jasmine.StyleFixtures.prototype.set = function (css) { 178 | this.cleanUp() 179 | this.createStyle_(css) 180 | } 181 | 182 | jasmine.StyleFixtures.prototype.appendSet = function (css) { 183 | this.createStyle_(css) 184 | } 185 | 186 | jasmine.StyleFixtures.prototype.preload = function () { 187 | this.read_.apply(this, arguments) 188 | } 189 | 190 | jasmine.StyleFixtures.prototype.load = function () { 191 | this.cleanUp() 192 | this.createStyle_(this.read_.apply(this, arguments)) 193 | } 194 | 195 | jasmine.StyleFixtures.prototype.appendLoad = function () { 196 | this.createStyle_(this.read_.apply(this, arguments)) 197 | } 198 | 199 | jasmine.StyleFixtures.prototype.cleanUp = function () { 200 | while(this.fixturesNodes_.length) { 201 | this.fixturesNodes_.pop().remove() 202 | } 203 | } 204 | 205 | jasmine.StyleFixtures.prototype.createStyle_ = function (html) { 206 | var styleText = $('
').html(html).text() 207 | , style = $('') 208 | 209 | this.fixturesNodes_.push(style) 210 | $('head').append(style) 211 | } 212 | 213 | jasmine.StyleFixtures.prototype.clearCache = jasmine.Fixtures.prototype.clearCache 214 | jasmine.StyleFixtures.prototype.read_ = jasmine.Fixtures.prototype.read 215 | jasmine.StyleFixtures.prototype.getFixtureHtml_ = jasmine.Fixtures.prototype.getFixtureHtml_ 216 | jasmine.StyleFixtures.prototype.loadFixtureIntoCache_ = jasmine.Fixtures.prototype.loadFixtureIntoCache_ 217 | jasmine.StyleFixtures.prototype.makeFixtureUrl_ = jasmine.Fixtures.prototype.makeFixtureUrl_ 218 | jasmine.StyleFixtures.prototype.proxyCallTo_ = jasmine.Fixtures.prototype.proxyCallTo_ 219 | 220 | jasmine.getJSONFixtures = function () { 221 | return jasmine.currentJSONFixtures_ = jasmine.currentJSONFixtures_ || new jasmine.JSONFixtures() 222 | } 223 | 224 | jasmine.JSONFixtures = function () { 225 | this.fixturesCache_ = {} 226 | this.fixturesPath = 'spec/javascripts/fixtures/json' 227 | } 228 | 229 | jasmine.JSONFixtures.prototype.load = function () { 230 | this.read.apply(this, arguments) 231 | return this.fixturesCache_ 232 | } 233 | 234 | jasmine.JSONFixtures.prototype.read = function () { 235 | var fixtureUrls = arguments 236 | 237 | for(var urlCount = fixtureUrls.length, urlIndex = 0; urlIndex < urlCount; urlIndex++) { 238 | this.getFixtureData_(fixtureUrls[urlIndex]) 239 | } 240 | 241 | return this.fixturesCache_ 242 | } 243 | 244 | jasmine.JSONFixtures.prototype.clearCache = function () { 245 | this.fixturesCache_ = {} 246 | } 247 | 248 | jasmine.JSONFixtures.prototype.getFixtureData_ = function (url) { 249 | if (!this.fixturesCache_[url]) this.loadFixtureIntoCache_(url) 250 | return this.fixturesCache_[url] 251 | } 252 | 253 | jasmine.JSONFixtures.prototype.loadFixtureIntoCache_ = function (relativeUrl) { 254 | var self = this 255 | , url = this.fixturesPath.match('/$') ? this.fixturesPath + relativeUrl : this.fixturesPath + '/' + relativeUrl 256 | 257 | $.ajax({ 258 | async: false, // must be synchronous to guarantee that no tests are run before fixture is loaded 259 | cache: false, 260 | dataType: 'json', 261 | url: url, 262 | success: function (data) { 263 | self.fixturesCache_[relativeUrl] = data 264 | }, 265 | error: function ($xhr, status, err) { 266 | throw new Error('JSONFixture could not be loaded: ' + url + ' (status: ' + status + ', message: ' + err.message + ')') 267 | } 268 | }) 269 | } 270 | 271 | jasmine.JSONFixtures.prototype.proxyCallTo_ = function (methodName, passedArguments) { 272 | return this[methodName].apply(this, passedArguments) 273 | } 274 | 275 | jasmine.jQuery = function () {} 276 | 277 | jasmine.jQuery.browserTagCaseIndependentHtml = function (html) { 278 | return $('
').append(html).html() 279 | } 280 | 281 | jasmine.jQuery.elementToString = function (element) { 282 | return $(element).map(function () { return this.outerHTML; }).toArray().join(', ') 283 | } 284 | 285 | var data = { 286 | spiedEvents: {} 287 | , handlers: [] 288 | } 289 | 290 | jasmine.jQuery.events = { 291 | spyOn: function (selector, eventName) { 292 | var handler = function (e) { 293 | var calls = (typeof data.spiedEvents[jasmine.spiedEventsKey(selector, eventName)] !== 'undefined') ? data.spiedEvents[jasmine.spiedEventsKey(selector, eventName)].calls : 0 294 | data.spiedEvents[jasmine.spiedEventsKey(selector, eventName)] = { 295 | args: jasmine.util.argsToArray(arguments), 296 | calls: ++calls 297 | } 298 | } 299 | 300 | $(selector).on(eventName, handler) 301 | data.handlers.push(handler) 302 | 303 | return { 304 | selector: selector, 305 | eventName: eventName, 306 | handler: handler, 307 | reset: function (){ 308 | delete data.spiedEvents[jasmine.spiedEventsKey(selector, eventName)] 309 | }, 310 | calls: { 311 | count: function () { 312 | return data.spiedEvents[jasmine.spiedEventsKey(selector, eventName)] ? 313 | data.spiedEvents[jasmine.spiedEventsKey(selector, eventName)].calls : 0; 314 | }, 315 | any: function () { 316 | return data.spiedEvents[jasmine.spiedEventsKey(selector, eventName)] ? 317 | !!data.spiedEvents[jasmine.spiedEventsKey(selector, eventName)].calls : false; 318 | } 319 | } 320 | } 321 | }, 322 | 323 | args: function (selector, eventName) { 324 | var actualArgs = data.spiedEvents[jasmine.spiedEventsKey(selector, eventName)].args 325 | 326 | if (!actualArgs) { 327 | throw "There is no spy for " + eventName + " on " + selector.toString() + ". Make sure to create a spy using spyOnEvent." 328 | } 329 | 330 | return actualArgs 331 | }, 332 | 333 | wasTriggered: function (selector, eventName) { 334 | return !!(data.spiedEvents[jasmine.spiedEventsKey(selector, eventName)]) 335 | }, 336 | 337 | wasTriggeredWith: function (selector, eventName, expectedArgs, util, customEqualityTesters) { 338 | var actualArgs = jasmine.jQuery.events.args(selector, eventName).slice(1) 339 | 340 | if (Object.prototype.toString.call(expectedArgs) !== '[object Array]') 341 | actualArgs = actualArgs[0] 342 | 343 | return util.equals(actualArgs, expectedArgs, customEqualityTesters) 344 | }, 345 | 346 | wasPrevented: function (selector, eventName) { 347 | var spiedEvent = data.spiedEvents[jasmine.spiedEventsKey(selector, eventName)] 348 | , args = (jasmine.util.isUndefined(spiedEvent)) ? {} : spiedEvent.args 349 | , e = args ? args[0] : undefined 350 | 351 | return e && e.isDefaultPrevented() 352 | }, 353 | 354 | wasStopped: function (selector, eventName) { 355 | var spiedEvent = data.spiedEvents[jasmine.spiedEventsKey(selector, eventName)] 356 | , args = (jasmine.util.isUndefined(spiedEvent)) ? {} : spiedEvent.args 357 | , e = args ? args[0] : undefined 358 | 359 | return e && e.isPropagationStopped() 360 | }, 361 | 362 | cleanUp: function () { 363 | data.spiedEvents = {} 364 | data.handlers = [] 365 | } 366 | } 367 | 368 | var hasProperty = function (actualValue, expectedValue) { 369 | if (expectedValue === undefined) 370 | return actualValue !== undefined 371 | 372 | return actualValue === expectedValue 373 | } 374 | 375 | beforeEach(function () { 376 | jasmine.addMatchers({ 377 | toHaveClass: function () { 378 | return { 379 | compare: function (actual, className) { 380 | return { pass: $(actual).hasClass(className) } 381 | } 382 | } 383 | }, 384 | 385 | toHaveCss: function () { 386 | return { 387 | compare: function (actual, css) { 388 | var stripCharsRegex = /[\s;\"\']/g 389 | for (var prop in css) { 390 | var value = css[prop] 391 | // see issue #147 on gh 392 | ;if ((value === 'auto') && ($(actual).get(0).style[prop] === 'auto')) continue 393 | var actualStripped = $(actual).css(prop).replace(stripCharsRegex, '') 394 | var valueStripped = value.replace(stripCharsRegex, '') 395 | if (actualStripped !== valueStripped) return { pass: false } 396 | } 397 | return { pass: true } 398 | } 399 | } 400 | }, 401 | 402 | toBeVisible: function () { 403 | return { 404 | compare: function (actual) { 405 | return { pass: $(actual).is(':visible') } 406 | } 407 | } 408 | }, 409 | 410 | toBeHidden: function () { 411 | return { 412 | compare: function (actual) { 413 | return { pass: $(actual).is(':hidden') } 414 | } 415 | } 416 | }, 417 | 418 | toBeSelected: function () { 419 | return { 420 | compare: function (actual) { 421 | return { pass: $(actual).is(':selected') } 422 | } 423 | } 424 | }, 425 | 426 | toBeChecked: function () { 427 | return { 428 | compare: function (actual) { 429 | return { pass: $(actual).is(':checked') } 430 | } 431 | } 432 | }, 433 | 434 | toBeEmpty: function () { 435 | return { 436 | compare: function (actual) { 437 | return { pass: $(actual).is(':empty') } 438 | } 439 | } 440 | }, 441 | 442 | toBeInDOM: function () { 443 | return { 444 | compare: function (actual) { 445 | return { pass: $.contains(document.documentElement, $(actual)[0]) } 446 | } 447 | } 448 | }, 449 | 450 | toExist: function () { 451 | return { 452 | compare: function (actual) { 453 | return { pass: $(actual).length } 454 | } 455 | } 456 | }, 457 | 458 | toHaveLength: function () { 459 | return { 460 | compare: function (actual, length) { 461 | return { pass: $(actual).length === length } 462 | } 463 | } 464 | }, 465 | 466 | toHaveAttr: function () { 467 | return { 468 | compare: function (actual, attributeName, expectedAttributeValue) { 469 | return { pass: hasProperty($(actual).attr(attributeName), expectedAttributeValue) } 470 | } 471 | } 472 | }, 473 | 474 | toHaveProp: function () { 475 | return { 476 | compare: function (actual, propertyName, expectedPropertyValue) { 477 | return { pass: hasProperty($(actual).prop(propertyName), expectedPropertyValue) } 478 | } 479 | } 480 | }, 481 | 482 | toHaveId: function () { 483 | return { 484 | compare: function (actual, id) { 485 | return { pass: $(actual).attr('id') == id } 486 | } 487 | } 488 | }, 489 | 490 | toHaveHtml: function () { 491 | return { 492 | compare: function (actual, html) { 493 | return { pass: $(actual).html() == jasmine.jQuery.browserTagCaseIndependentHtml(html) } 494 | } 495 | } 496 | }, 497 | 498 | toContainHtml: function () { 499 | return { 500 | compare: function (actual, html) { 501 | var actualHtml = $(actual).html() 502 | , expectedHtml = jasmine.jQuery.browserTagCaseIndependentHtml(html) 503 | 504 | return { pass: (actualHtml.indexOf(expectedHtml) >= 0) } 505 | } 506 | } 507 | }, 508 | 509 | toHaveText: function () { 510 | return { 511 | compare: function (actual, text) { 512 | var actualText = $(actual).text() 513 | var trimmedText = $.trim(actualText) 514 | 515 | if (text && $.isFunction(text.test)) { 516 | return { pass: text.test(actualText) || text.test(trimmedText) } 517 | } else { 518 | return { pass: (actualText == text || trimmedText == text) } 519 | } 520 | } 521 | } 522 | }, 523 | 524 | toContainText: function () { 525 | return { 526 | compare: function (actual, text) { 527 | var trimmedText = $.trim($(actual).text()) 528 | 529 | if (text && $.isFunction(text.test)) { 530 | return { pass: text.test(trimmedText) } 531 | } else { 532 | return { pass: trimmedText.indexOf(text) != -1 } 533 | } 534 | } 535 | } 536 | }, 537 | 538 | toHaveValue: function () { 539 | return { 540 | compare: function (actual, value) { 541 | return { pass: $(actual).val() === value } 542 | } 543 | } 544 | }, 545 | 546 | toHaveData: function () { 547 | return { 548 | compare: function (actual, key, expectedValue) { 549 | return { pass: hasProperty($(actual).data(key), expectedValue) } 550 | } 551 | } 552 | }, 553 | 554 | toContainElement: function () { 555 | return { 556 | compare: function (actual, selector) { 557 | return { pass: $(actual).find(selector).length } 558 | } 559 | } 560 | }, 561 | 562 | toBeMatchedBy: function () { 563 | return { 564 | compare: function (actual, selector) { 565 | return { pass: $(actual).filter(selector).length } 566 | } 567 | } 568 | }, 569 | 570 | toBeDisabled: function () { 571 | return { 572 | compare: function (actual, selector) { 573 | return { pass: $(actual).is(':disabled') } 574 | } 575 | } 576 | }, 577 | 578 | toBeFocused: function (selector) { 579 | return { 580 | compare: function (actual, selector) { 581 | return { pass: $(actual)[0] === $(actual)[0].ownerDocument.activeElement } 582 | } 583 | } 584 | }, 585 | 586 | toHandle: function () { 587 | return { 588 | compare: function (actual, event) { 589 | if ( !actual || actual.length === 0 ) return { pass: false }; 590 | var events = $._data($(actual).get(0), "events") 591 | 592 | if (!events || !event || typeof event !== "string") { 593 | return { pass: false } 594 | } 595 | 596 | var namespaces = event.split(".") 597 | , eventType = namespaces.shift() 598 | , sortedNamespaces = namespaces.slice(0).sort() 599 | , namespaceRegExp = new RegExp("(^|\\.)" + sortedNamespaces.join("\\.(?:.*\\.)?") + "(\\.|$)") 600 | 601 | if (events[eventType] && namespaces.length) { 602 | for (var i = 0; i < events[eventType].length; i++) { 603 | var namespace = events[eventType][i].namespace 604 | 605 | if (namespaceRegExp.test(namespace)) 606 | return { pass: true } 607 | } 608 | } else { 609 | return { pass: (events[eventType] && events[eventType].length > 0) } 610 | } 611 | 612 | return { pass: false } 613 | } 614 | } 615 | }, 616 | 617 | toHandleWith: function () { 618 | return { 619 | compare: function (actual, eventName, eventHandler) { 620 | if ( !actual || actual.length === 0 ) return { pass: false }; 621 | var normalizedEventName = eventName.split('.')[0] 622 | , stack = $._data($(actual).get(0), "events")[normalizedEventName] 623 | 624 | for (var i = 0; i < stack.length; i++) { 625 | if (stack[i].handler == eventHandler) return { pass: true } 626 | } 627 | 628 | return { pass: false } 629 | } 630 | } 631 | }, 632 | 633 | toHaveBeenTriggeredOn: function () { 634 | return { 635 | compare: function (actual, selector) { 636 | var result = { pass: jasmine.jQuery.events.wasTriggered(selector, actual) } 637 | 638 | result.message = result.pass ? 639 | "Expected event " + $(actual) + " not to have been triggered on " + selector : 640 | "Expected event " + $(actual) + " to have been triggered on " + selector 641 | 642 | return result; 643 | } 644 | } 645 | }, 646 | 647 | toHaveBeenTriggered: function (){ 648 | return { 649 | compare: function (actual) { 650 | var eventName = actual.eventName 651 | , selector = actual.selector 652 | , result = { pass: jasmine.jQuery.events.wasTriggered(selector, eventName) } 653 | 654 | result.message = result.pass ? 655 | "Expected event " + eventName + " not to have been triggered on " + selector : 656 | "Expected event " + eventName + " to have been triggered on " + selector 657 | 658 | return result 659 | } 660 | } 661 | }, 662 | 663 | toHaveBeenTriggeredOnAndWith: function (j$, customEqualityTesters) { 664 | return { 665 | compare: function (actual, selector, expectedArgs) { 666 | var wasTriggered = jasmine.jQuery.events.wasTriggered(selector, actual) 667 | , result = { pass: wasTriggered && jasmine.jQuery.events.wasTriggeredWith(selector, actual, expectedArgs, j$, customEqualityTesters) } 668 | 669 | if (wasTriggered) { 670 | var actualArgs = jasmine.jQuery.events.args(selector, actual, expectedArgs)[1] 671 | result.message = result.pass ? 672 | "Expected event " + actual + " not to have been triggered with " + jasmine.pp(expectedArgs) + " but it was triggered with " + jasmine.pp(actualArgs) : 673 | "Expected event " + actual + " to have been triggered with " + jasmine.pp(expectedArgs) + " but it was triggered with " + jasmine.pp(actualArgs) 674 | 675 | } else { 676 | // todo check on this 677 | result.message = result.pass ? 678 | "Expected event " + actual + " not to have been triggered on " + selector : 679 | "Expected event " + actual + " to have been triggered on " + selector 680 | } 681 | 682 | return result 683 | } 684 | } 685 | }, 686 | 687 | toHaveBeenPreventedOn: function () { 688 | return { 689 | compare: function (actual, selector) { 690 | var result = { pass: jasmine.jQuery.events.wasPrevented(selector, actual) } 691 | 692 | result.message = result.pass ? 693 | "Expected event " + actual + " not to have been prevented on " + selector : 694 | "Expected event " + actual + " to have been prevented on " + selector 695 | 696 | return result 697 | } 698 | } 699 | }, 700 | 701 | toHaveBeenPrevented: function () { 702 | return { 703 | compare: function (actual) { 704 | var eventName = actual.eventName 705 | , selector = actual.selector 706 | , result = { pass: jasmine.jQuery.events.wasPrevented(selector, eventName) } 707 | 708 | result.message = result.pass ? 709 | "Expected event " + eventName + " not to have been prevented on " + selector : 710 | "Expected event " + eventName + " to have been prevented on " + selector 711 | 712 | return result 713 | } 714 | } 715 | }, 716 | 717 | toHaveBeenStoppedOn: function () { 718 | return { 719 | compare: function (actual, selector) { 720 | var result = { pass: jasmine.jQuery.events.wasStopped(selector, actual) } 721 | 722 | result.message = result.pass ? 723 | "Expected event " + actual + " not to have been stopped on " + selector : 724 | "Expected event " + actual + " to have been stopped on " + selector 725 | 726 | return result; 727 | } 728 | } 729 | }, 730 | 731 | toHaveBeenStopped: function () { 732 | return { 733 | compare: function (actual) { 734 | var eventName = actual.eventName 735 | , selector = actual.selector 736 | , result = { pass: jasmine.jQuery.events.wasStopped(selector, eventName) } 737 | 738 | result.message = result.pass ? 739 | "Expected event " + eventName + " not to have been stopped on " + selector : 740 | "Expected event " + eventName + " to have been stopped on " + selector 741 | 742 | return result 743 | } 744 | } 745 | } 746 | }) 747 | 748 | jasmine.getEnv().addCustomEqualityTester(function(a, b) { 749 | if (a && b) { 750 | if (a instanceof $ || jasmine.isDomNode(a)) { 751 | var $a = $(a) 752 | 753 | if (b instanceof $) 754 | return $a.length == b.length && a.is(b) 755 | 756 | return $a.is(b); 757 | } 758 | 759 | if (b instanceof $ || jasmine.isDomNode(b)) { 760 | var $b = $(b) 761 | 762 | if (a instanceof $) 763 | return a.length == $b.length && $b.is(a) 764 | 765 | return $(b).is(a); 766 | } 767 | } 768 | }) 769 | 770 | jasmine.getEnv().addCustomEqualityTester(function (a, b) { 771 | if (a instanceof $ && b instanceof $ && a.size() == b.size()) 772 | return a.is(b) 773 | }) 774 | }) 775 | 776 | afterEach(function () { 777 | jasmine.getFixtures().cleanUp() 778 | jasmine.getStyleFixtures().cleanUp() 779 | jasmine.jQuery.events.cleanUp() 780 | }) 781 | 782 | window.readFixtures = function () { 783 | return jasmine.getFixtures().proxyCallTo_('read', arguments) 784 | } 785 | 786 | window.preloadFixtures = function () { 787 | jasmine.getFixtures().proxyCallTo_('preload', arguments) 788 | } 789 | 790 | window.loadFixtures = function () { 791 | jasmine.getFixtures().proxyCallTo_('load', arguments) 792 | } 793 | 794 | window.appendLoadFixtures = function () { 795 | jasmine.getFixtures().proxyCallTo_('appendLoad', arguments) 796 | } 797 | 798 | window.setFixtures = function (html) { 799 | return jasmine.getFixtures().proxyCallTo_('set', arguments) 800 | } 801 | 802 | window.appendSetFixtures = function () { 803 | jasmine.getFixtures().proxyCallTo_('appendSet', arguments) 804 | } 805 | 806 | window.sandbox = function (attributes) { 807 | return jasmine.getFixtures().sandbox(attributes) 808 | } 809 | 810 | window.spyOnEvent = function (selector, eventName) { 811 | return jasmine.jQuery.events.spyOn(selector, eventName) 812 | } 813 | 814 | window.preloadStyleFixtures = function () { 815 | jasmine.getStyleFixtures().proxyCallTo_('preload', arguments) 816 | } 817 | 818 | window.loadStyleFixtures = function () { 819 | jasmine.getStyleFixtures().proxyCallTo_('load', arguments) 820 | } 821 | 822 | window.appendLoadStyleFixtures = function () { 823 | jasmine.getStyleFixtures().proxyCallTo_('appendLoad', arguments) 824 | } 825 | 826 | window.setStyleFixtures = function (html) { 827 | jasmine.getStyleFixtures().proxyCallTo_('set', arguments) 828 | } 829 | 830 | window.appendSetStyleFixtures = function (html) { 831 | jasmine.getStyleFixtures().proxyCallTo_('appendSet', arguments) 832 | } 833 | 834 | window.loadJSONFixtures = function () { 835 | return jasmine.getJSONFixtures().proxyCallTo_('load', arguments) 836 | } 837 | 838 | window.getJSONFixture = function (url) { 839 | return jasmine.getJSONFixtures().proxyCallTo_('read', arguments)[url] 840 | } 841 | })); 842 | -------------------------------------------------------------------------------- /lib/jasmine-2.4.1/jquery-3.1.0.min.js: -------------------------------------------------------------------------------- 1 | /*! jQuery v3.1.0 | (c) jQuery Foundation | jquery.org/license */ 2 | !function(a,b){"use strict";"object"==typeof module&&"object"==typeof module.exports?module.exports=a.document?b(a,!0):function(a){if(!a.document)throw new Error("jQuery requires a window with a document");return b(a)}:b(a)}("undefined"!=typeof window?window:this,function(a,b){"use strict";var c=[],d=a.document,e=Object.getPrototypeOf,f=c.slice,g=c.concat,h=c.push,i=c.indexOf,j={},k=j.toString,l=j.hasOwnProperty,m=l.toString,n=m.call(Object),o={};function p(a,b){b=b||d;var c=b.createElement("script");c.text=a,b.head.appendChild(c).parentNode.removeChild(c)}var q="3.1.0",r=function(a,b){return new r.fn.init(a,b)},s=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,t=/^-ms-/,u=/-([a-z])/g,v=function(a,b){return b.toUpperCase()};r.fn=r.prototype={jquery:q,constructor:r,length:0,toArray:function(){return f.call(this)},get:function(a){return null!=a?a<0?this[a+this.length]:this[a]:f.call(this)},pushStack:function(a){var b=r.merge(this.constructor(),a);return b.prevObject=this,b},each:function(a){return r.each(this,a)},map:function(a){return this.pushStack(r.map(this,function(b,c){return a.call(b,c,b)}))},slice:function(){return this.pushStack(f.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(a){var b=this.length,c=+a+(a<0?b:0);return this.pushStack(c>=0&&c0&&b-1 in a)}var x=function(a){var b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u="sizzle"+1*new Date,v=a.document,w=0,x=0,y=ha(),z=ha(),A=ha(),B=function(a,b){return a===b&&(l=!0),0},C={}.hasOwnProperty,D=[],E=D.pop,F=D.push,G=D.push,H=D.slice,I=function(a,b){for(var c=0,d=a.length;c+~]|"+K+")"+K+"*"),S=new RegExp("="+K+"*([^\\]'\"]*?)"+K+"*\\]","g"),T=new RegExp(N),U=new RegExp("^"+L+"$"),V={ID:new RegExp("^#("+L+")"),CLASS:new RegExp("^\\.("+L+")"),TAG:new RegExp("^("+L+"|[*])"),ATTR:new RegExp("^"+M),PSEUDO:new RegExp("^"+N),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+K+"*(even|odd|(([+-]|)(\\d*)n|)"+K+"*(?:([+-]|)"+K+"*(\\d+)|))"+K+"*\\)|)","i"),bool:new RegExp("^(?:"+J+")$","i"),needsContext:new RegExp("^"+K+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+K+"*((?:-\\d)?\\d*)"+K+"*\\)|)(?=[^-]|$)","i")},W=/^(?:input|select|textarea|button)$/i,X=/^h\d$/i,Y=/^[^{]+\{\s*\[native \w/,Z=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,$=/[+~]/,_=new RegExp("\\\\([\\da-f]{1,6}"+K+"?|("+K+")|.)","ig"),aa=function(a,b,c){var d="0x"+b-65536;return d!==d||c?b:d<0?String.fromCharCode(d+65536):String.fromCharCode(d>>10|55296,1023&d|56320)},ba=/([\0-\x1f\x7f]|^-?\d)|^-$|[^\x80-\uFFFF\w-]/g,ca=function(a,b){return b?"\0"===a?"\ufffd":a.slice(0,-1)+"\\"+a.charCodeAt(a.length-1).toString(16)+" ":"\\"+a},da=function(){m()},ea=ta(function(a){return a.disabled===!0},{dir:"parentNode",next:"legend"});try{G.apply(D=H.call(v.childNodes),v.childNodes),D[v.childNodes.length].nodeType}catch(fa){G={apply:D.length?function(a,b){F.apply(a,H.call(b))}:function(a,b){var c=a.length,d=0;while(a[c++]=b[d++]);a.length=c-1}}}function ga(a,b,d,e){var f,h,j,k,l,o,r,s=b&&b.ownerDocument,w=b?b.nodeType:9;if(d=d||[],"string"!=typeof a||!a||1!==w&&9!==w&&11!==w)return d;if(!e&&((b?b.ownerDocument||b:v)!==n&&m(b),b=b||n,p)){if(11!==w&&(l=Z.exec(a)))if(f=l[1]){if(9===w){if(!(j=b.getElementById(f)))return d;if(j.id===f)return d.push(j),d}else if(s&&(j=s.getElementById(f))&&t(b,j)&&j.id===f)return d.push(j),d}else{if(l[2])return G.apply(d,b.getElementsByTagName(a)),d;if((f=l[3])&&c.getElementsByClassName&&b.getElementsByClassName)return G.apply(d,b.getElementsByClassName(f)),d}if(c.qsa&&!A[a+" "]&&(!q||!q.test(a))){if(1!==w)s=b,r=a;else if("object"!==b.nodeName.toLowerCase()){(k=b.getAttribute("id"))?k=k.replace(ba,ca):b.setAttribute("id",k=u),o=g(a),h=o.length;while(h--)o[h]="#"+k+" "+sa(o[h]);r=o.join(","),s=$.test(a)&&qa(b.parentNode)||b}if(r)try{return G.apply(d,s.querySelectorAll(r)),d}catch(x){}finally{k===u&&b.removeAttribute("id")}}}return i(a.replace(P,"$1"),b,d,e)}function ha(){var a=[];function b(c,e){return a.push(c+" ")>d.cacheLength&&delete b[a.shift()],b[c+" "]=e}return b}function ia(a){return a[u]=!0,a}function ja(a){var b=n.createElement("fieldset");try{return!!a(b)}catch(c){return!1}finally{b.parentNode&&b.parentNode.removeChild(b),b=null}}function ka(a,b){var c=a.split("|"),e=c.length;while(e--)d.attrHandle[c[e]]=b}function la(a,b){var c=b&&a,d=c&&1===a.nodeType&&1===b.nodeType&&a.sourceIndex-b.sourceIndex;if(d)return d;if(c)while(c=c.nextSibling)if(c===b)return-1;return a?1:-1}function ma(a){return function(b){var c=b.nodeName.toLowerCase();return"input"===c&&b.type===a}}function na(a){return function(b){var c=b.nodeName.toLowerCase();return("input"===c||"button"===c)&&b.type===a}}function oa(a){return function(b){return"label"in b&&b.disabled===a||"form"in b&&b.disabled===a||"form"in b&&b.disabled===!1&&(b.isDisabled===a||b.isDisabled!==!a&&("label"in b||!ea(b))!==a)}}function pa(a){return ia(function(b){return b=+b,ia(function(c,d){var e,f=a([],c.length,b),g=f.length;while(g--)c[e=f[g]]&&(c[e]=!(d[e]=c[e]))})})}function qa(a){return a&&"undefined"!=typeof a.getElementsByTagName&&a}c=ga.support={},f=ga.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return!!b&&"HTML"!==b.nodeName},m=ga.setDocument=function(a){var b,e,g=a?a.ownerDocument||a:v;return g!==n&&9===g.nodeType&&g.documentElement?(n=g,o=n.documentElement,p=!f(n),v!==n&&(e=n.defaultView)&&e.top!==e&&(e.addEventListener?e.addEventListener("unload",da,!1):e.attachEvent&&e.attachEvent("onunload",da)),c.attributes=ja(function(a){return a.className="i",!a.getAttribute("className")}),c.getElementsByTagName=ja(function(a){return a.appendChild(n.createComment("")),!a.getElementsByTagName("*").length}),c.getElementsByClassName=Y.test(n.getElementsByClassName),c.getById=ja(function(a){return o.appendChild(a).id=u,!n.getElementsByName||!n.getElementsByName(u).length}),c.getById?(d.find.ID=function(a,b){if("undefined"!=typeof b.getElementById&&p){var c=b.getElementById(a);return c?[c]:[]}},d.filter.ID=function(a){var b=a.replace(_,aa);return function(a){return a.getAttribute("id")===b}}):(delete d.find.ID,d.filter.ID=function(a){var b=a.replace(_,aa);return function(a){var c="undefined"!=typeof a.getAttributeNode&&a.getAttributeNode("id");return c&&c.value===b}}),d.find.TAG=c.getElementsByTagName?function(a,b){return"undefined"!=typeof b.getElementsByTagName?b.getElementsByTagName(a):c.qsa?b.querySelectorAll(a):void 0}:function(a,b){var c,d=[],e=0,f=b.getElementsByTagName(a);if("*"===a){while(c=f[e++])1===c.nodeType&&d.push(c);return d}return f},d.find.CLASS=c.getElementsByClassName&&function(a,b){if("undefined"!=typeof b.getElementsByClassName&&p)return b.getElementsByClassName(a)},r=[],q=[],(c.qsa=Y.test(n.querySelectorAll))&&(ja(function(a){o.appendChild(a).innerHTML="",a.querySelectorAll("[msallowcapture^='']").length&&q.push("[*^$]="+K+"*(?:''|\"\")"),a.querySelectorAll("[selected]").length||q.push("\\["+K+"*(?:value|"+J+")"),a.querySelectorAll("[id~="+u+"-]").length||q.push("~="),a.querySelectorAll(":checked").length||q.push(":checked"),a.querySelectorAll("a#"+u+"+*").length||q.push(".#.+[+~]")}),ja(function(a){a.innerHTML="";var b=n.createElement("input");b.setAttribute("type","hidden"),a.appendChild(b).setAttribute("name","D"),a.querySelectorAll("[name=d]").length&&q.push("name"+K+"*[*^$|!~]?="),2!==a.querySelectorAll(":enabled").length&&q.push(":enabled",":disabled"),o.appendChild(a).disabled=!0,2!==a.querySelectorAll(":disabled").length&&q.push(":enabled",":disabled"),a.querySelectorAll("*,:x"),q.push(",.*:")})),(c.matchesSelector=Y.test(s=o.matches||o.webkitMatchesSelector||o.mozMatchesSelector||o.oMatchesSelector||o.msMatchesSelector))&&ja(function(a){c.disconnectedMatch=s.call(a,"*"),s.call(a,"[s!='']:x"),r.push("!=",N)}),q=q.length&&new RegExp(q.join("|")),r=r.length&&new RegExp(r.join("|")),b=Y.test(o.compareDocumentPosition),t=b||Y.test(o.contains)?function(a,b){var c=9===a.nodeType?a.documentElement:a,d=b&&b.parentNode;return a===d||!(!d||1!==d.nodeType||!(c.contains?c.contains(d):a.compareDocumentPosition&&16&a.compareDocumentPosition(d)))}:function(a,b){if(b)while(b=b.parentNode)if(b===a)return!0;return!1},B=b?function(a,b){if(a===b)return l=!0,0;var d=!a.compareDocumentPosition-!b.compareDocumentPosition;return d?d:(d=(a.ownerDocument||a)===(b.ownerDocument||b)?a.compareDocumentPosition(b):1,1&d||!c.sortDetached&&b.compareDocumentPosition(a)===d?a===n||a.ownerDocument===v&&t(v,a)?-1:b===n||b.ownerDocument===v&&t(v,b)?1:k?I(k,a)-I(k,b):0:4&d?-1:1)}:function(a,b){if(a===b)return l=!0,0;var c,d=0,e=a.parentNode,f=b.parentNode,g=[a],h=[b];if(!e||!f)return a===n?-1:b===n?1:e?-1:f?1:k?I(k,a)-I(k,b):0;if(e===f)return la(a,b);c=a;while(c=c.parentNode)g.unshift(c);c=b;while(c=c.parentNode)h.unshift(c);while(g[d]===h[d])d++;return d?la(g[d],h[d]):g[d]===v?-1:h[d]===v?1:0},n):n},ga.matches=function(a,b){return ga(a,null,null,b)},ga.matchesSelector=function(a,b){if((a.ownerDocument||a)!==n&&m(a),b=b.replace(S,"='$1']"),c.matchesSelector&&p&&!A[b+" "]&&(!r||!r.test(b))&&(!q||!q.test(b)))try{var d=s.call(a,b);if(d||c.disconnectedMatch||a.document&&11!==a.document.nodeType)return d}catch(e){}return ga(b,n,null,[a]).length>0},ga.contains=function(a,b){return(a.ownerDocument||a)!==n&&m(a),t(a,b)},ga.attr=function(a,b){(a.ownerDocument||a)!==n&&m(a);var e=d.attrHandle[b.toLowerCase()],f=e&&C.call(d.attrHandle,b.toLowerCase())?e(a,b,!p):void 0;return void 0!==f?f:c.attributes||!p?a.getAttribute(b):(f=a.getAttributeNode(b))&&f.specified?f.value:null},ga.escape=function(a){return(a+"").replace(ba,ca)},ga.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)},ga.uniqueSort=function(a){var b,d=[],e=0,f=0;if(l=!c.detectDuplicates,k=!c.sortStable&&a.slice(0),a.sort(B),l){while(b=a[f++])b===a[f]&&(e=d.push(f));while(e--)a.splice(d[e],1)}return k=null,a},e=ga.getText=function(a){var b,c="",d=0,f=a.nodeType;if(f){if(1===f||9===f||11===f){if("string"==typeof a.textContent)return a.textContent;for(a=a.firstChild;a;a=a.nextSibling)c+=e(a)}else if(3===f||4===f)return a.nodeValue}else while(b=a[d++])c+=e(b);return c},d=ga.selectors={cacheLength:50,createPseudo:ia,match:V,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(a){return a[1]=a[1].replace(_,aa),a[3]=(a[3]||a[4]||a[5]||"").replace(_,aa),"~="===a[2]&&(a[3]=" "+a[3]+" "),a.slice(0,4)},CHILD:function(a){return a[1]=a[1].toLowerCase(),"nth"===a[1].slice(0,3)?(a[3]||ga.error(a[0]),a[4]=+(a[4]?a[5]+(a[6]||1):2*("even"===a[3]||"odd"===a[3])),a[5]=+(a[7]+a[8]||"odd"===a[3])):a[3]&&ga.error(a[0]),a},PSEUDO:function(a){var b,c=!a[6]&&a[2];return V.CHILD.test(a[0])?null:(a[3]?a[2]=a[4]||a[5]||"":c&&T.test(c)&&(b=g(c,!0))&&(b=c.indexOf(")",c.length-b)-c.length)&&(a[0]=a[0].slice(0,b),a[2]=c.slice(0,b)),a.slice(0,3))}},filter:{TAG:function(a){var b=a.replace(_,aa).toLowerCase();return"*"===a?function(){return!0}:function(a){return a.nodeName&&a.nodeName.toLowerCase()===b}},CLASS:function(a){var b=y[a+" "];return b||(b=new RegExp("(^|"+K+")"+a+"("+K+"|$)"))&&y(a,function(a){return b.test("string"==typeof a.className&&a.className||"undefined"!=typeof a.getAttribute&&a.getAttribute("class")||"")})},ATTR:function(a,b,c){return function(d){var e=ga.attr(d,a);return null==e?"!="===b:!b||(e+="","="===b?e===c:"!="===b?e!==c:"^="===b?c&&0===e.indexOf(c):"*="===b?c&&e.indexOf(c)>-1:"$="===b?c&&e.slice(-c.length)===c:"~="===b?(" "+e.replace(O," ")+" ").indexOf(c)>-1:"|="===b&&(e===c||e.slice(0,c.length+1)===c+"-"))}},CHILD:function(a,b,c,d,e){var f="nth"!==a.slice(0,3),g="last"!==a.slice(-4),h="of-type"===b;return 1===d&&0===e?function(a){return!!a.parentNode}:function(b,c,i){var j,k,l,m,n,o,p=f!==g?"nextSibling":"previousSibling",q=b.parentNode,r=h&&b.nodeName.toLowerCase(),s=!i&&!h,t=!1;if(q){if(f){while(p){m=b;while(m=m[p])if(h?m.nodeName.toLowerCase()===r:1===m.nodeType)return!1;o=p="only"===a&&!o&&"nextSibling"}return!0}if(o=[g?q.firstChild:q.lastChild],g&&s){m=q,l=m[u]||(m[u]={}),k=l[m.uniqueID]||(l[m.uniqueID]={}),j=k[a]||[],n=j[0]===w&&j[1],t=n&&j[2],m=n&&q.childNodes[n];while(m=++n&&m&&m[p]||(t=n=0)||o.pop())if(1===m.nodeType&&++t&&m===b){k[a]=[w,n,t];break}}else if(s&&(m=b,l=m[u]||(m[u]={}),k=l[m.uniqueID]||(l[m.uniqueID]={}),j=k[a]||[],n=j[0]===w&&j[1],t=n),t===!1)while(m=++n&&m&&m[p]||(t=n=0)||o.pop())if((h?m.nodeName.toLowerCase()===r:1===m.nodeType)&&++t&&(s&&(l=m[u]||(m[u]={}),k=l[m.uniqueID]||(l[m.uniqueID]={}),k[a]=[w,t]),m===b))break;return t-=e,t===d||t%d===0&&t/d>=0}}},PSEUDO:function(a,b){var c,e=d.pseudos[a]||d.setFilters[a.toLowerCase()]||ga.error("unsupported pseudo: "+a);return e[u]?e(b):e.length>1?(c=[a,a,"",b],d.setFilters.hasOwnProperty(a.toLowerCase())?ia(function(a,c){var d,f=e(a,b),g=f.length;while(g--)d=I(a,f[g]),a[d]=!(c[d]=f[g])}):function(a){return e(a,0,c)}):e}},pseudos:{not:ia(function(a){var b=[],c=[],d=h(a.replace(P,"$1"));return d[u]?ia(function(a,b,c,e){var f,g=d(a,null,e,[]),h=a.length;while(h--)(f=g[h])&&(a[h]=!(b[h]=f))}):function(a,e,f){return b[0]=a,d(b,null,f,c),b[0]=null,!c.pop()}}),has:ia(function(a){return function(b){return ga(a,b).length>0}}),contains:ia(function(a){return a=a.replace(_,aa),function(b){return(b.textContent||b.innerText||e(b)).indexOf(a)>-1}}),lang:ia(function(a){return U.test(a||"")||ga.error("unsupported lang: "+a),a=a.replace(_,aa).toLowerCase(),function(b){var c;do if(c=p?b.lang:b.getAttribute("xml:lang")||b.getAttribute("lang"))return c=c.toLowerCase(),c===a||0===c.indexOf(a+"-");while((b=b.parentNode)&&1===b.nodeType);return!1}}),target:function(b){var c=a.location&&a.location.hash;return c&&c.slice(1)===b.id},root:function(a){return a===o},focus:function(a){return a===n.activeElement&&(!n.hasFocus||n.hasFocus())&&!!(a.type||a.href||~a.tabIndex)},enabled:oa(!1),disabled:oa(!0),checked:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&!!a.checked||"option"===b&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},empty:function(a){for(a=a.firstChild;a;a=a.nextSibling)if(a.nodeType<6)return!1;return!0},parent:function(a){return!d.pseudos.empty(a)},header:function(a){return X.test(a.nodeName)},input:function(a){return W.test(a.nodeName)},button:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&"button"===a.type||"button"===b},text:function(a){var b;return"input"===a.nodeName.toLowerCase()&&"text"===a.type&&(null==(b=a.getAttribute("type"))||"text"===b.toLowerCase())},first:pa(function(){return[0]}),last:pa(function(a,b){return[b-1]}),eq:pa(function(a,b,c){return[c<0?c+b:c]}),even:pa(function(a,b){for(var c=0;c=0;)a.push(d);return a}),gt:pa(function(a,b,c){for(var d=c<0?c+b:c;++d1?function(b,c,d){var e=a.length;while(e--)if(!a[e](b,c,d))return!1;return!0}:a[0]}function va(a,b,c){for(var d=0,e=b.length;d-1&&(f[j]=!(g[j]=l))}}else r=wa(r===g?r.splice(o,r.length):r),e?e(null,g,r,i):G.apply(g,r)})}function ya(a){for(var b,c,e,f=a.length,g=d.relative[a[0].type],h=g||d.relative[" "],i=g?1:0,k=ta(function(a){return a===b},h,!0),l=ta(function(a){return I(b,a)>-1},h,!0),m=[function(a,c,d){var e=!g&&(d||c!==j)||((b=c).nodeType?k(a,c,d):l(a,c,d));return b=null,e}];i1&&ua(m),i>1&&sa(a.slice(0,i-1).concat({value:" "===a[i-2].type?"*":""})).replace(P,"$1"),c,i0,e=a.length>0,f=function(f,g,h,i,k){var l,o,q,r=0,s="0",t=f&&[],u=[],v=j,x=f||e&&d.find.TAG("*",k),y=w+=null==v?1:Math.random()||.1,z=x.length;for(k&&(j=g===n||g||k);s!==z&&null!=(l=x[s]);s++){if(e&&l){o=0,g||l.ownerDocument===n||(m(l),h=!p);while(q=a[o++])if(q(l,g||n,h)){i.push(l);break}k&&(w=y)}c&&((l=!q&&l)&&r--,f&&t.push(l))}if(r+=s,c&&s!==r){o=0;while(q=b[o++])q(t,u,g,h);if(f){if(r>0)while(s--)t[s]||u[s]||(u[s]=E.call(i));u=wa(u)}G.apply(i,u),k&&!f&&u.length>0&&r+b.length>1&&ga.uniqueSort(i)}return k&&(w=y,j=v),t};return c?ia(f):f}return h=ga.compile=function(a,b){var c,d=[],e=[],f=A[a+" "];if(!f){b||(b=g(a)),c=b.length;while(c--)f=ya(b[c]),f[u]?d.push(f):e.push(f);f=A(a,za(e,d)),f.selector=a}return f},i=ga.select=function(a,b,e,f){var i,j,k,l,m,n="function"==typeof a&&a,o=!f&&g(a=n.selector||a);if(e=e||[],1===o.length){if(j=o[0]=o[0].slice(0),j.length>2&&"ID"===(k=j[0]).type&&c.getById&&9===b.nodeType&&p&&d.relative[j[1].type]){if(b=(d.find.ID(k.matches[0].replace(_,aa),b)||[])[0],!b)return e;n&&(b=b.parentNode),a=a.slice(j.shift().value.length)}i=V.needsContext.test(a)?0:j.length;while(i--){if(k=j[i],d.relative[l=k.type])break;if((m=d.find[l])&&(f=m(k.matches[0].replace(_,aa),$.test(j[0].type)&&qa(b.parentNode)||b))){if(j.splice(i,1),a=f.length&&sa(j),!a)return G.apply(e,f),e;break}}}return(n||h(a,o))(f,b,!p,e,!b||$.test(a)&&qa(b.parentNode)||b),e},c.sortStable=u.split("").sort(B).join("")===u,c.detectDuplicates=!!l,m(),c.sortDetached=ja(function(a){return 1&a.compareDocumentPosition(n.createElement("fieldset"))}),ja(function(a){return a.innerHTML="","#"===a.firstChild.getAttribute("href")})||ka("type|href|height|width",function(a,b,c){if(!c)return a.getAttribute(b,"type"===b.toLowerCase()?1:2)}),c.attributes&&ja(function(a){return a.innerHTML="",a.firstChild.setAttribute("value",""),""===a.firstChild.getAttribute("value")})||ka("value",function(a,b,c){if(!c&&"input"===a.nodeName.toLowerCase())return a.defaultValue}),ja(function(a){return null==a.getAttribute("disabled")})||ka(J,function(a,b,c){var d;if(!c)return a[b]===!0?b.toLowerCase():(d=a.getAttributeNode(b))&&d.specified?d.value:null}),ga}(a);r.find=x,r.expr=x.selectors,r.expr[":"]=r.expr.pseudos,r.uniqueSort=r.unique=x.uniqueSort,r.text=x.getText,r.isXMLDoc=x.isXML,r.contains=x.contains,r.escapeSelector=x.escape;var y=function(a,b,c){var d=[],e=void 0!==c;while((a=a[b])&&9!==a.nodeType)if(1===a.nodeType){if(e&&r(a).is(c))break;d.push(a)}return d},z=function(a,b){for(var c=[];a;a=a.nextSibling)1===a.nodeType&&a!==b&&c.push(a);return c},A=r.expr.match.needsContext,B=/^<([a-z][^\/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i,C=/^.[^:#\[\.,]*$/;function D(a,b,c){if(r.isFunction(b))return r.grep(a,function(a,d){return!!b.call(a,d,a)!==c});if(b.nodeType)return r.grep(a,function(a){return a===b!==c});if("string"==typeof b){if(C.test(b))return r.filter(b,a,c);b=r.filter(b,a)}return r.grep(a,function(a){return i.call(b,a)>-1!==c&&1===a.nodeType})}r.filter=function(a,b,c){var d=b[0];return c&&(a=":not("+a+")"),1===b.length&&1===d.nodeType?r.find.matchesSelector(d,a)?[d]:[]:r.find.matches(a,r.grep(b,function(a){return 1===a.nodeType}))},r.fn.extend({find:function(a){var b,c,d=this.length,e=this;if("string"!=typeof a)return this.pushStack(r(a).filter(function(){for(b=0;b1?r.uniqueSort(c):c},filter:function(a){return this.pushStack(D(this,a||[],!1))},not:function(a){return this.pushStack(D(this,a||[],!0))},is:function(a){return!!D(this,"string"==typeof a&&A.test(a)?r(a):a||[],!1).length}});var E,F=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]+))$/,G=r.fn.init=function(a,b,c){var e,f;if(!a)return this;if(c=c||E,"string"==typeof a){if(e="<"===a[0]&&">"===a[a.length-1]&&a.length>=3?[null,a,null]:F.exec(a),!e||!e[1]&&b)return!b||b.jquery?(b||c).find(a):this.constructor(b).find(a);if(e[1]){if(b=b instanceof r?b[0]:b,r.merge(this,r.parseHTML(e[1],b&&b.nodeType?b.ownerDocument||b:d,!0)),B.test(e[1])&&r.isPlainObject(b))for(e in b)r.isFunction(this[e])?this[e](b[e]):this.attr(e,b[e]);return this}return f=d.getElementById(e[2]),f&&(this[0]=f,this.length=1),this}return a.nodeType?(this[0]=a,this.length=1,this):r.isFunction(a)?void 0!==c.ready?c.ready(a):a(r):r.makeArray(a,this)};G.prototype=r.fn,E=r(d);var H=/^(?:parents|prev(?:Until|All))/,I={children:!0,contents:!0,next:!0,prev:!0};r.fn.extend({has:function(a){var b=r(a,this),c=b.length;return this.filter(function(){for(var a=0;a-1:1===c.nodeType&&r.find.matchesSelector(c,a))){f.push(c);break}return this.pushStack(f.length>1?r.uniqueSort(f):f)},index:function(a){return a?"string"==typeof a?i.call(r(a),this[0]):i.call(this,a.jquery?a[0]:a):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(a,b){return this.pushStack(r.uniqueSort(r.merge(this.get(),r(a,b))))},addBack:function(a){return this.add(null==a?this.prevObject:this.prevObject.filter(a))}});function J(a,b){while((a=a[b])&&1!==a.nodeType);return a}r.each({parent:function(a){var b=a.parentNode;return b&&11!==b.nodeType?b:null},parents:function(a){return y(a,"parentNode")},parentsUntil:function(a,b,c){return y(a,"parentNode",c)},next:function(a){return J(a,"nextSibling")},prev:function(a){return J(a,"previousSibling")},nextAll:function(a){return y(a,"nextSibling")},prevAll:function(a){return y(a,"previousSibling")},nextUntil:function(a,b,c){return y(a,"nextSibling",c)},prevUntil:function(a,b,c){return y(a,"previousSibling",c)},siblings:function(a){return z((a.parentNode||{}).firstChild,a)},children:function(a){return z(a.firstChild)},contents:function(a){return a.contentDocument||r.merge([],a.childNodes)}},function(a,b){r.fn[a]=function(c,d){var e=r.map(this,b,c);return"Until"!==a.slice(-5)&&(d=c),d&&"string"==typeof d&&(e=r.filter(d,e)),this.length>1&&(I[a]||r.uniqueSort(e),H.test(a)&&e.reverse()),this.pushStack(e)}});var K=/\S+/g;function L(a){var b={};return r.each(a.match(K)||[],function(a,c){b[c]=!0}),b}r.Callbacks=function(a){a="string"==typeof a?L(a):r.extend({},a);var b,c,d,e,f=[],g=[],h=-1,i=function(){for(e=a.once,d=b=!0;g.length;h=-1){c=g.shift();while(++h-1)f.splice(c,1),c<=h&&h--}),this},has:function(a){return a?r.inArray(a,f)>-1:f.length>0},empty:function(){return f&&(f=[]),this},disable:function(){return e=g=[],f=c="",this},disabled:function(){return!f},lock:function(){return e=g=[],c||b||(f=c=""),this},locked:function(){return!!e},fireWith:function(a,c){return e||(c=c||[],c=[a,c.slice?c.slice():c],g.push(c),b||i()),this},fire:function(){return j.fireWith(this,arguments),this},fired:function(){return!!d}};return j};function M(a){return a}function N(a){throw a}function O(a,b,c){var d;try{a&&r.isFunction(d=a.promise)?d.call(a).done(b).fail(c):a&&r.isFunction(d=a.then)?d.call(a,b,c):b.call(void 0,a)}catch(a){c.call(void 0,a)}}r.extend({Deferred:function(b){var c=[["notify","progress",r.Callbacks("memory"),r.Callbacks("memory"),2],["resolve","done",r.Callbacks("once memory"),r.Callbacks("once memory"),0,"resolved"],["reject","fail",r.Callbacks("once memory"),r.Callbacks("once memory"),1,"rejected"]],d="pending",e={state:function(){return d},always:function(){return f.done(arguments).fail(arguments),this},"catch":function(a){return e.then(null,a)},pipe:function(){var a=arguments;return r.Deferred(function(b){r.each(c,function(c,d){var e=r.isFunction(a[d[4]])&&a[d[4]];f[d[1]](function(){var a=e&&e.apply(this,arguments);a&&r.isFunction(a.promise)?a.promise().progress(b.notify).done(b.resolve).fail(b.reject):b[d[0]+"With"](this,e?[a]:arguments)})}),a=null}).promise()},then:function(b,d,e){var f=0;function g(b,c,d,e){return function(){var h=this,i=arguments,j=function(){var a,j;if(!(b=f&&(d!==N&&(h=void 0,i=[a]),c.rejectWith(h,i))}};b?k():(r.Deferred.getStackHook&&(k.stackTrace=r.Deferred.getStackHook()),a.setTimeout(k))}}return r.Deferred(function(a){c[0][3].add(g(0,a,r.isFunction(e)?e:M,a.notifyWith)),c[1][3].add(g(0,a,r.isFunction(b)?b:M)),c[2][3].add(g(0,a,r.isFunction(d)?d:N))}).promise()},promise:function(a){return null!=a?r.extend(a,e):e}},f={};return r.each(c,function(a,b){var g=b[2],h=b[5];e[b[1]]=g.add,h&&g.add(function(){d=h},c[3-a][2].disable,c[0][2].lock),g.add(b[3].fire),f[b[0]]=function(){return f[b[0]+"With"](this===f?void 0:this,arguments),this},f[b[0]+"With"]=g.fireWith}),e.promise(f),b&&b.call(f,f),f},when:function(a){var b=arguments.length,c=b,d=Array(c),e=f.call(arguments),g=r.Deferred(),h=function(a){return function(c){d[a]=this,e[a]=arguments.length>1?f.call(arguments):c,--b||g.resolveWith(d,e)}};if(b<=1&&(O(a,g.done(h(c)).resolve,g.reject),"pending"===g.state()||r.isFunction(e[c]&&e[c].then)))return g.then();while(c--)O(e[c],h(c),g.reject);return g.promise()}});var P=/^(Eval|Internal|Range|Reference|Syntax|Type|URI)Error$/;r.Deferred.exceptionHook=function(b,c){a.console&&a.console.warn&&b&&P.test(b.name)&&a.console.warn("jQuery.Deferred exception: "+b.message,b.stack,c)},r.readyException=function(b){a.setTimeout(function(){throw b})};var Q=r.Deferred();r.fn.ready=function(a){return Q.then(a)["catch"](function(a){r.readyException(a)}),this},r.extend({isReady:!1,readyWait:1,holdReady:function(a){a?r.readyWait++:r.ready(!0)},ready:function(a){(a===!0?--r.readyWait:r.isReady)||(r.isReady=!0,a!==!0&&--r.readyWait>0||Q.resolveWith(d,[r]))}}),r.ready.then=Q.then;function R(){d.removeEventListener("DOMContentLoaded",R),a.removeEventListener("load",R),r.ready()}"complete"===d.readyState||"loading"!==d.readyState&&!d.documentElement.doScroll?a.setTimeout(r.ready):(d.addEventListener("DOMContentLoaded",R),a.addEventListener("load",R));var S=function(a,b,c,d,e,f,g){var h=0,i=a.length,j=null==c;if("object"===r.type(c)){e=!0;for(h in c)S(a,b,h,c[h],!0,f,g)}else if(void 0!==d&&(e=!0, 3 | r.isFunction(d)||(g=!0),j&&(g?(b.call(a,d),b=null):(j=b,b=function(a,b,c){return j.call(r(a),c)})),b))for(;h1,null,!0)},removeData:function(a){return this.each(function(){W.remove(this,a)})}}),r.extend({queue:function(a,b,c){var d;if(a)return b=(b||"fx")+"queue",d=V.get(a,b),c&&(!d||r.isArray(c)?d=V.access(a,b,r.makeArray(c)):d.push(c)),d||[]},dequeue:function(a,b){b=b||"fx";var c=r.queue(a,b),d=c.length,e=c.shift(),f=r._queueHooks(a,b),g=function(){r.dequeue(a,b)};"inprogress"===e&&(e=c.shift(),d--),e&&("fx"===b&&c.unshift("inprogress"),delete f.stop,e.call(a,g,f)),!d&&f&&f.empty.fire()},_queueHooks:function(a,b){var c=b+"queueHooks";return V.get(a,c)||V.access(a,c,{empty:r.Callbacks("once memory").add(function(){V.remove(a,[b+"queue",c])})})}}),r.fn.extend({queue:function(a,b){var c=2;return"string"!=typeof a&&(b=a,a="fx",c--),arguments.length\x20\t\r\n\f]+)/i,ja=/^$|\/(?:java|ecma)script/i,ka={option:[1,""],thead:[1,"","
"],col:[2,"","
"],tr:[2,"","
"],td:[3,"","
"],_default:[0,"",""]};ka.optgroup=ka.option,ka.tbody=ka.tfoot=ka.colgroup=ka.caption=ka.thead,ka.th=ka.td;function la(a,b){var c="undefined"!=typeof a.getElementsByTagName?a.getElementsByTagName(b||"*"):"undefined"!=typeof a.querySelectorAll?a.querySelectorAll(b||"*"):[];return void 0===b||b&&r.nodeName(a,b)?r.merge([a],c):c}function ma(a,b){for(var c=0,d=a.length;c-1)e&&e.push(f);else if(j=r.contains(f.ownerDocument,f),g=la(l.appendChild(f),"script"),j&&ma(g),c){k=0;while(f=g[k++])ja.test(f.type||"")&&c.push(f)}return l}!function(){var a=d.createDocumentFragment(),b=a.appendChild(d.createElement("div")),c=d.createElement("input");c.setAttribute("type","radio"),c.setAttribute("checked","checked"),c.setAttribute("name","t"),b.appendChild(c),o.checkClone=b.cloneNode(!0).cloneNode(!0).lastChild.checked,b.innerHTML="",o.noCloneChecked=!!b.cloneNode(!0).lastChild.defaultValue}();var pa=d.documentElement,qa=/^key/,ra=/^(?:mouse|pointer|contextmenu|drag|drop)|click/,sa=/^([^.]*)(?:\.(.+)|)/;function ta(){return!0}function ua(){return!1}function va(){try{return d.activeElement}catch(a){}}function wa(a,b,c,d,e,f){var g,h;if("object"==typeof b){"string"!=typeof c&&(d=d||c,c=void 0);for(h in b)wa(a,h,c,d,b[h],f);return a}if(null==d&&null==e?(e=c,d=c=void 0):null==e&&("string"==typeof c?(e=d,d=void 0):(e=d,d=c,c=void 0)),e===!1)e=ua;else if(!e)return a;return 1===f&&(g=e,e=function(a){return r().off(a),g.apply(this,arguments)},e.guid=g.guid||(g.guid=r.guid++)),a.each(function(){r.event.add(this,b,e,d,c)})}r.event={global:{},add:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,n,o,p,q=V.get(a);if(q){c.handler&&(f=c,c=f.handler,e=f.selector),e&&r.find.matchesSelector(pa,e),c.guid||(c.guid=r.guid++),(i=q.events)||(i=q.events={}),(g=q.handle)||(g=q.handle=function(b){return"undefined"!=typeof r&&r.event.triggered!==b.type?r.event.dispatch.apply(a,arguments):void 0}),b=(b||"").match(K)||[""],j=b.length;while(j--)h=sa.exec(b[j])||[],n=p=h[1],o=(h[2]||"").split(".").sort(),n&&(l=r.event.special[n]||{},n=(e?l.delegateType:l.bindType)||n,l=r.event.special[n]||{},k=r.extend({type:n,origType:p,data:d,handler:c,guid:c.guid,selector:e,needsContext:e&&r.expr.match.needsContext.test(e),namespace:o.join(".")},f),(m=i[n])||(m=i[n]=[],m.delegateCount=0,l.setup&&l.setup.call(a,d,o,g)!==!1||a.addEventListener&&a.addEventListener(n,g)),l.add&&(l.add.call(a,k),k.handler.guid||(k.handler.guid=c.guid)),e?m.splice(m.delegateCount++,0,k):m.push(k),r.event.global[n]=!0)}},remove:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,n,o,p,q=V.hasData(a)&&V.get(a);if(q&&(i=q.events)){b=(b||"").match(K)||[""],j=b.length;while(j--)if(h=sa.exec(b[j])||[],n=p=h[1],o=(h[2]||"").split(".").sort(),n){l=r.event.special[n]||{},n=(d?l.delegateType:l.bindType)||n,m=i[n]||[],h=h[2]&&new RegExp("(^|\\.)"+o.join("\\.(?:.*\\.|)")+"(\\.|$)"),g=f=m.length;while(f--)k=m[f],!e&&p!==k.origType||c&&c.guid!==k.guid||h&&!h.test(k.namespace)||d&&d!==k.selector&&("**"!==d||!k.selector)||(m.splice(f,1),k.selector&&m.delegateCount--,l.remove&&l.remove.call(a,k));g&&!m.length&&(l.teardown&&l.teardown.call(a,o,q.handle)!==!1||r.removeEvent(a,n,q.handle),delete i[n])}else for(n in i)r.event.remove(a,n+b[j],c,d,!0);r.isEmptyObject(i)&&V.remove(a,"handle events")}},dispatch:function(a){var b=r.event.fix(a),c,d,e,f,g,h,i=new Array(arguments.length),j=(V.get(this,"events")||{})[b.type]||[],k=r.event.special[b.type]||{};for(i[0]=b,c=1;c-1:r.find(e,this,null,[i]).length),d[e]&&d.push(f);d.length&&g.push({elem:i,handlers:d})}return h\x20\t\r\n\f]*)[^>]*)\/>/gi,ya=/\s*$/g;function Ca(a,b){return r.nodeName(a,"table")&&r.nodeName(11!==b.nodeType?b:b.firstChild,"tr")?a.getElementsByTagName("tbody")[0]||a:a}function Da(a){return a.type=(null!==a.getAttribute("type"))+"/"+a.type,a}function Ea(a){var b=Aa.exec(a.type);return b?a.type=b[1]:a.removeAttribute("type"),a}function Fa(a,b){var c,d,e,f,g,h,i,j;if(1===b.nodeType){if(V.hasData(a)&&(f=V.access(a),g=V.set(b,f),j=f.events)){delete g.handle,g.events={};for(e in j)for(c=0,d=j[e].length;c1&&"string"==typeof q&&!o.checkClone&&za.test(q))return a.each(function(e){var f=a.eq(e);s&&(b[0]=q.call(this,e,f.html())),Ha(f,b,c,d)});if(m&&(e=oa(b,a[0].ownerDocument,!1,a,d),f=e.firstChild,1===e.childNodes.length&&(e=f),f||d)){for(h=r.map(la(e,"script"),Da),i=h.length;l")},clone:function(a,b,c){var d,e,f,g,h=a.cloneNode(!0),i=r.contains(a.ownerDocument,a);if(!(o.noCloneChecked||1!==a.nodeType&&11!==a.nodeType||r.isXMLDoc(a)))for(g=la(h),f=la(a),d=0,e=f.length;d0&&ma(g,!i&&la(a,"script")),h},cleanData:function(a){for(var b,c,d,e=r.event.special,f=0;void 0!==(c=a[f]);f++)if(T(c)){if(b=c[V.expando]){if(b.events)for(d in b.events)e[d]?r.event.remove(c,d):r.removeEvent(c,d,b.handle);c[V.expando]=void 0}c[W.expando]&&(c[W.expando]=void 0)}}}),r.fn.extend({detach:function(a){return Ia(this,a,!0)},remove:function(a){return Ia(this,a)},text:function(a){return S(this,function(a){return void 0===a?r.text(this):this.empty().each(function(){1!==this.nodeType&&11!==this.nodeType&&9!==this.nodeType||(this.textContent=a)})},null,a,arguments.length)},append:function(){return Ha(this,arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=Ca(this,a);b.appendChild(a)}})},prepend:function(){return Ha(this,arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=Ca(this,a);b.insertBefore(a,b.firstChild)}})},before:function(){return Ha(this,arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this)})},after:function(){return Ha(this,arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this.nextSibling)})},empty:function(){for(var a,b=0;null!=(a=this[b]);b++)1===a.nodeType&&(r.cleanData(la(a,!1)),a.textContent="");return this},clone:function(a,b){return a=null!=a&&a,b=null==b?a:b,this.map(function(){return r.clone(this,a,b)})},html:function(a){return S(this,function(a){var b=this[0]||{},c=0,d=this.length;if(void 0===a&&1===b.nodeType)return b.innerHTML;if("string"==typeof a&&!ya.test(a)&&!ka[(ia.exec(a)||["",""])[1].toLowerCase()]){a=r.htmlPrefilter(a);try{for(;c1)}});function Xa(a,b,c,d,e){return new Xa.prototype.init(a,b,c,d,e)}r.Tween=Xa,Xa.prototype={constructor:Xa,init:function(a,b,c,d,e,f){this.elem=a,this.prop=c,this.easing=e||r.easing._default,this.options=b,this.start=this.now=this.cur(),this.end=d,this.unit=f||(r.cssNumber[c]?"":"px")},cur:function(){var a=Xa.propHooks[this.prop];return a&&a.get?a.get(this):Xa.propHooks._default.get(this)},run:function(a){var b,c=Xa.propHooks[this.prop];return this.options.duration?this.pos=b=r.easing[this.easing](a,this.options.duration*a,0,1,this.options.duration):this.pos=b=a,this.now=(this.end-this.start)*b+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),c&&c.set?c.set(this):Xa.propHooks._default.set(this),this}},Xa.prototype.init.prototype=Xa.prototype,Xa.propHooks={_default:{get:function(a){var b;return 1!==a.elem.nodeType||null!=a.elem[a.prop]&&null==a.elem.style[a.prop]?a.elem[a.prop]:(b=r.css(a.elem,a.prop,""),b&&"auto"!==b?b:0)},set:function(a){r.fx.step[a.prop]?r.fx.step[a.prop](a):1!==a.elem.nodeType||null==a.elem.style[r.cssProps[a.prop]]&&!r.cssHooks[a.prop]?a.elem[a.prop]=a.now:r.style(a.elem,a.prop,a.now+a.unit)}}},Xa.propHooks.scrollTop=Xa.propHooks.scrollLeft={set:function(a){a.elem.nodeType&&a.elem.parentNode&&(a.elem[a.prop]=a.now)}},r.easing={linear:function(a){return a},swing:function(a){return.5-Math.cos(a*Math.PI)/2},_default:"swing"},r.fx=Xa.prototype.init,r.fx.step={};var Ya,Za,$a=/^(?:toggle|show|hide)$/,_a=/queueHooks$/;function ab(){Za&&(a.requestAnimationFrame(ab),r.fx.tick())}function bb(){return a.setTimeout(function(){Ya=void 0}),Ya=r.now()}function cb(a,b){var c,d=0,e={height:a};for(b=b?1:0;d<4;d+=2-b)c=aa[d],e["margin"+c]=e["padding"+c]=a;return b&&(e.opacity=e.width=a),e}function db(a,b,c){for(var d,e=(gb.tweeners[b]||[]).concat(gb.tweeners["*"]),f=0,g=e.length;f1)},removeAttr:function(a){return this.each(function(){r.removeAttr(this,a)})}}),r.extend({attr:function(a,b,c){var d,e,f=a.nodeType;if(3!==f&&8!==f&&2!==f)return"undefined"==typeof a.getAttribute?r.prop(a,b,c):(1===f&&r.isXMLDoc(a)||(e=r.attrHooks[b.toLowerCase()]||(r.expr.match.bool.test(b)?hb:void 0)),void 0!==c?null===c?void r.removeAttr(a,b):e&&"set"in e&&void 0!==(d=e.set(a,c,b))?d:(a.setAttribute(b,c+""),c):e&&"get"in e&&null!==(d=e.get(a,b))?d:(d=r.find.attr(a,b),null==d?void 0:d))},attrHooks:{type:{set:function(a,b){if(!o.radioValue&&"radio"===b&&r.nodeName(a,"input")){var c=a.value;return a.setAttribute("type",b),c&&(a.value=c),b}}}},removeAttr:function(a,b){var c,d=0,e=b&&b.match(K); 4 | if(e&&1===a.nodeType)while(c=e[d++])a.removeAttribute(c)}}),hb={set:function(a,b,c){return b===!1?r.removeAttr(a,c):a.setAttribute(c,c),c}},r.each(r.expr.match.bool.source.match(/\w+/g),function(a,b){var c=ib[b]||r.find.attr;ib[b]=function(a,b,d){var e,f,g=b.toLowerCase();return d||(f=ib[g],ib[g]=e,e=null!=c(a,b,d)?g:null,ib[g]=f),e}});var jb=/^(?:input|select|textarea|button)$/i,kb=/^(?:a|area)$/i;r.fn.extend({prop:function(a,b){return S(this,r.prop,a,b,arguments.length>1)},removeProp:function(a){return this.each(function(){delete this[r.propFix[a]||a]})}}),r.extend({prop:function(a,b,c){var d,e,f=a.nodeType;if(3!==f&&8!==f&&2!==f)return 1===f&&r.isXMLDoc(a)||(b=r.propFix[b]||b,e=r.propHooks[b]),void 0!==c?e&&"set"in e&&void 0!==(d=e.set(a,c,b))?d:a[b]=c:e&&"get"in e&&null!==(d=e.get(a,b))?d:a[b]},propHooks:{tabIndex:{get:function(a){var b=r.find.attr(a,"tabindex");return b?parseInt(b,10):jb.test(a.nodeName)||kb.test(a.nodeName)&&a.href?0:-1}}},propFix:{"for":"htmlFor","class":"className"}}),o.optSelected||(r.propHooks.selected={get:function(a){var b=a.parentNode;return b&&b.parentNode&&b.parentNode.selectedIndex,null},set:function(a){var b=a.parentNode;b&&(b.selectedIndex,b.parentNode&&b.parentNode.selectedIndex)}}),r.each(["tabIndex","readOnly","maxLength","cellSpacing","cellPadding","rowSpan","colSpan","useMap","frameBorder","contentEditable"],function(){r.propFix[this.toLowerCase()]=this});var lb=/[\t\r\n\f]/g;function mb(a){return a.getAttribute&&a.getAttribute("class")||""}r.fn.extend({addClass:function(a){var b,c,d,e,f,g,h,i=0;if(r.isFunction(a))return this.each(function(b){r(this).addClass(a.call(this,b,mb(this)))});if("string"==typeof a&&a){b=a.match(K)||[];while(c=this[i++])if(e=mb(c),d=1===c.nodeType&&(" "+e+" ").replace(lb," ")){g=0;while(f=b[g++])d.indexOf(" "+f+" ")<0&&(d+=f+" ");h=r.trim(d),e!==h&&c.setAttribute("class",h)}}return this},removeClass:function(a){var b,c,d,e,f,g,h,i=0;if(r.isFunction(a))return this.each(function(b){r(this).removeClass(a.call(this,b,mb(this)))});if(!arguments.length)return this.attr("class","");if("string"==typeof a&&a){b=a.match(K)||[];while(c=this[i++])if(e=mb(c),d=1===c.nodeType&&(" "+e+" ").replace(lb," ")){g=0;while(f=b[g++])while(d.indexOf(" "+f+" ")>-1)d=d.replace(" "+f+" "," ");h=r.trim(d),e!==h&&c.setAttribute("class",h)}}return this},toggleClass:function(a,b){var c=typeof a;return"boolean"==typeof b&&"string"===c?b?this.addClass(a):this.removeClass(a):r.isFunction(a)?this.each(function(c){r(this).toggleClass(a.call(this,c,mb(this),b),b)}):this.each(function(){var b,d,e,f;if("string"===c){d=0,e=r(this),f=a.match(K)||[];while(b=f[d++])e.hasClass(b)?e.removeClass(b):e.addClass(b)}else void 0!==a&&"boolean"!==c||(b=mb(this),b&&V.set(this,"__className__",b),this.setAttribute&&this.setAttribute("class",b||a===!1?"":V.get(this,"__className__")||""))})},hasClass:function(a){var b,c,d=0;b=" "+a+" ";while(c=this[d++])if(1===c.nodeType&&(" "+mb(c)+" ").replace(lb," ").indexOf(b)>-1)return!0;return!1}});var nb=/\r/g,ob=/[\x20\t\r\n\f]+/g;r.fn.extend({val:function(a){var b,c,d,e=this[0];{if(arguments.length)return d=r.isFunction(a),this.each(function(c){var e;1===this.nodeType&&(e=d?a.call(this,c,r(this).val()):a,null==e?e="":"number"==typeof e?e+="":r.isArray(e)&&(e=r.map(e,function(a){return null==a?"":a+""})),b=r.valHooks[this.type]||r.valHooks[this.nodeName.toLowerCase()],b&&"set"in b&&void 0!==b.set(this,e,"value")||(this.value=e))});if(e)return b=r.valHooks[e.type]||r.valHooks[e.nodeName.toLowerCase()],b&&"get"in b&&void 0!==(c=b.get(e,"value"))?c:(c=e.value,"string"==typeof c?c.replace(nb,""):null==c?"":c)}}}),r.extend({valHooks:{option:{get:function(a){var b=r.find.attr(a,"value");return null!=b?b:r.trim(r.text(a)).replace(ob," ")}},select:{get:function(a){for(var b,c,d=a.options,e=a.selectedIndex,f="select-one"===a.type,g=f?null:[],h=f?e+1:d.length,i=e<0?h:f?e:0;i-1)&&(c=!0);return c||(a.selectedIndex=-1),f}}}}),r.each(["radio","checkbox"],function(){r.valHooks[this]={set:function(a,b){if(r.isArray(b))return a.checked=r.inArray(r(a).val(),b)>-1}},o.checkOn||(r.valHooks[this].get=function(a){return null===a.getAttribute("value")?"on":a.value})});var pb=/^(?:focusinfocus|focusoutblur)$/;r.extend(r.event,{trigger:function(b,c,e,f){var g,h,i,j,k,m,n,o=[e||d],p=l.call(b,"type")?b.type:b,q=l.call(b,"namespace")?b.namespace.split("."):[];if(h=i=e=e||d,3!==e.nodeType&&8!==e.nodeType&&!pb.test(p+r.event.triggered)&&(p.indexOf(".")>-1&&(q=p.split("."),p=q.shift(),q.sort()),k=p.indexOf(":")<0&&"on"+p,b=b[r.expando]?b:new r.Event(p,"object"==typeof b&&b),b.isTrigger=f?2:3,b.namespace=q.join("."),b.rnamespace=b.namespace?new RegExp("(^|\\.)"+q.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,b.result=void 0,b.target||(b.target=e),c=null==c?[b]:r.makeArray(c,[b]),n=r.event.special[p]||{},f||!n.trigger||n.trigger.apply(e,c)!==!1)){if(!f&&!n.noBubble&&!r.isWindow(e)){for(j=n.delegateType||p,pb.test(j+p)||(h=h.parentNode);h;h=h.parentNode)o.push(h),i=h;i===(e.ownerDocument||d)&&o.push(i.defaultView||i.parentWindow||a)}g=0;while((h=o[g++])&&!b.isPropagationStopped())b.type=g>1?j:n.bindType||p,m=(V.get(h,"events")||{})[b.type]&&V.get(h,"handle"),m&&m.apply(h,c),m=k&&h[k],m&&m.apply&&T(h)&&(b.result=m.apply(h,c),b.result===!1&&b.preventDefault());return b.type=p,f||b.isDefaultPrevented()||n._default&&n._default.apply(o.pop(),c)!==!1||!T(e)||k&&r.isFunction(e[p])&&!r.isWindow(e)&&(i=e[k],i&&(e[k]=null),r.event.triggered=p,e[p](),r.event.triggered=void 0,i&&(e[k]=i)),b.result}},simulate:function(a,b,c){var d=r.extend(new r.Event,c,{type:a,isSimulated:!0});r.event.trigger(d,null,b)}}),r.fn.extend({trigger:function(a,b){return this.each(function(){r.event.trigger(a,b,this)})},triggerHandler:function(a,b){var c=this[0];if(c)return r.event.trigger(a,b,c,!0)}}),r.each("blur focus focusin focusout resize scroll click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup contextmenu".split(" "),function(a,b){r.fn[b]=function(a,c){return arguments.length>0?this.on(b,null,a,c):this.trigger(b)}}),r.fn.extend({hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)}}),o.focusin="onfocusin"in a,o.focusin||r.each({focus:"focusin",blur:"focusout"},function(a,b){var c=function(a){r.event.simulate(b,a.target,r.event.fix(a))};r.event.special[b]={setup:function(){var d=this.ownerDocument||this,e=V.access(d,b);e||d.addEventListener(a,c,!0),V.access(d,b,(e||0)+1)},teardown:function(){var d=this.ownerDocument||this,e=V.access(d,b)-1;e?V.access(d,b,e):(d.removeEventListener(a,c,!0),V.remove(d,b))}}});var qb=a.location,rb=r.now(),sb=/\?/;r.parseXML=function(b){var c;if(!b||"string"!=typeof b)return null;try{c=(new a.DOMParser).parseFromString(b,"text/xml")}catch(d){c=void 0}return c&&!c.getElementsByTagName("parsererror").length||r.error("Invalid XML: "+b),c};var tb=/\[\]$/,ub=/\r?\n/g,vb=/^(?:submit|button|image|reset|file)$/i,wb=/^(?:input|select|textarea|keygen)/i;function xb(a,b,c,d){var e;if(r.isArray(b))r.each(b,function(b,e){c||tb.test(a)?d(a,e):xb(a+"["+("object"==typeof e&&null!=e?b:"")+"]",e,c,d)});else if(c||"object"!==r.type(b))d(a,b);else for(e in b)xb(a+"["+e+"]",b[e],c,d)}r.param=function(a,b){var c,d=[],e=function(a,b){var c=r.isFunction(b)?b():b;d[d.length]=encodeURIComponent(a)+"="+encodeURIComponent(null==c?"":c)};if(r.isArray(a)||a.jquery&&!r.isPlainObject(a))r.each(a,function(){e(this.name,this.value)});else for(c in a)xb(c,a[c],b,e);return d.join("&")},r.fn.extend({serialize:function(){return r.param(this.serializeArray())},serializeArray:function(){return this.map(function(){var a=r.prop(this,"elements");return a?r.makeArray(a):this}).filter(function(){var a=this.type;return this.name&&!r(this).is(":disabled")&&wb.test(this.nodeName)&&!vb.test(a)&&(this.checked||!ha.test(a))}).map(function(a,b){var c=r(this).val();return null==c?null:r.isArray(c)?r.map(c,function(a){return{name:b.name,value:a.replace(ub,"\r\n")}}):{name:b.name,value:c.replace(ub,"\r\n")}}).get()}});var yb=/%20/g,zb=/#.*$/,Ab=/([?&])_=[^&]*/,Bb=/^(.*?):[ \t]*([^\r\n]*)$/gm,Cb=/^(?:about|app|app-storage|.+-extension|file|res|widget):$/,Db=/^(?:GET|HEAD)$/,Eb=/^\/\//,Fb={},Gb={},Hb="*/".concat("*"),Ib=d.createElement("a");Ib.href=qb.href;function Jb(a){return function(b,c){"string"!=typeof b&&(c=b,b="*");var d,e=0,f=b.toLowerCase().match(K)||[];if(r.isFunction(c))while(d=f[e++])"+"===d[0]?(d=d.slice(1)||"*",(a[d]=a[d]||[]).unshift(c)):(a[d]=a[d]||[]).push(c)}}function Kb(a,b,c,d){var e={},f=a===Gb;function g(h){var i;return e[h]=!0,r.each(a[h]||[],function(a,h){var j=h(b,c,d);return"string"!=typeof j||f||e[j]?f?!(i=j):void 0:(b.dataTypes.unshift(j),g(j),!1)}),i}return g(b.dataTypes[0])||!e["*"]&&g("*")}function Lb(a,b){var c,d,e=r.ajaxSettings.flatOptions||{};for(c in b)void 0!==b[c]&&((e[c]?a:d||(d={}))[c]=b[c]);return d&&r.extend(!0,a,d),a}function Mb(a,b,c){var d,e,f,g,h=a.contents,i=a.dataTypes;while("*"===i[0])i.shift(),void 0===d&&(d=a.mimeType||b.getResponseHeader("Content-Type"));if(d)for(e in h)if(h[e]&&h[e].test(d)){i.unshift(e);break}if(i[0]in c)f=i[0];else{for(e in c){if(!i[0]||a.converters[e+" "+i[0]]){f=e;break}g||(g=e)}f=f||g}if(f)return f!==i[0]&&i.unshift(f),c[f]}function Nb(a,b,c,d){var e,f,g,h,i,j={},k=a.dataTypes.slice();if(k[1])for(g in a.converters)j[g.toLowerCase()]=a.converters[g];f=k.shift();while(f)if(a.responseFields[f]&&(c[a.responseFields[f]]=b),!i&&d&&a.dataFilter&&(b=a.dataFilter(b,a.dataType)),i=f,f=k.shift())if("*"===f)f=i;else if("*"!==i&&i!==f){if(g=j[i+" "+f]||j["* "+f],!g)for(e in j)if(h=e.split(" "),h[1]===f&&(g=j[i+" "+h[0]]||j["* "+h[0]])){g===!0?g=j[e]:j[e]!==!0&&(f=h[0],k.unshift(h[1]));break}if(g!==!0)if(g&&a["throws"])b=g(b);else try{b=g(b)}catch(l){return{state:"parsererror",error:g?l:"No conversion from "+i+" to "+f}}}return{state:"success",data:b}}r.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:qb.href,type:"GET",isLocal:Cb.test(qb.protocol),global:!0,processData:!0,async:!0,contentType:"application/x-www-form-urlencoded; charset=UTF-8",accepts:{"*":Hb,text:"text/plain",html:"text/html",xml:"application/xml, text/xml",json:"application/json, text/javascript"},contents:{xml:/\bxml\b/,html:/\bhtml/,json:/\bjson\b/},responseFields:{xml:"responseXML",text:"responseText",json:"responseJSON"},converters:{"* text":String,"text html":!0,"text json":JSON.parse,"text xml":r.parseXML},flatOptions:{url:!0,context:!0}},ajaxSetup:function(a,b){return b?Lb(Lb(a,r.ajaxSettings),b):Lb(r.ajaxSettings,a)},ajaxPrefilter:Jb(Fb),ajaxTransport:Jb(Gb),ajax:function(b,c){"object"==typeof b&&(c=b,b=void 0),c=c||{};var e,f,g,h,i,j,k,l,m,n,o=r.ajaxSetup({},c),p=o.context||o,q=o.context&&(p.nodeType||p.jquery)?r(p):r.event,s=r.Deferred(),t=r.Callbacks("once memory"),u=o.statusCode||{},v={},w={},x="canceled",y={readyState:0,getResponseHeader:function(a){var b;if(k){if(!h){h={};while(b=Bb.exec(g))h[b[1].toLowerCase()]=b[2]}b=h[a.toLowerCase()]}return null==b?null:b},getAllResponseHeaders:function(){return k?g:null},setRequestHeader:function(a,b){return null==k&&(a=w[a.toLowerCase()]=w[a.toLowerCase()]||a,v[a]=b),this},overrideMimeType:function(a){return null==k&&(o.mimeType=a),this},statusCode:function(a){var b;if(a)if(k)y.always(a[y.status]);else for(b in a)u[b]=[u[b],a[b]];return this},abort:function(a){var b=a||x;return e&&e.abort(b),A(0,b),this}};if(s.promise(y),o.url=((b||o.url||qb.href)+"").replace(Eb,qb.protocol+"//"),o.type=c.method||c.type||o.method||o.type,o.dataTypes=(o.dataType||"*").toLowerCase().match(K)||[""],null==o.crossDomain){j=d.createElement("a");try{j.href=o.url,j.href=j.href,o.crossDomain=Ib.protocol+"//"+Ib.host!=j.protocol+"//"+j.host}catch(z){o.crossDomain=!0}}if(o.data&&o.processData&&"string"!=typeof o.data&&(o.data=r.param(o.data,o.traditional)),Kb(Fb,o,c,y),k)return y;l=r.event&&o.global,l&&0===r.active++&&r.event.trigger("ajaxStart"),o.type=o.type.toUpperCase(),o.hasContent=!Db.test(o.type),f=o.url.replace(zb,""),o.hasContent?o.data&&o.processData&&0===(o.contentType||"").indexOf("application/x-www-form-urlencoded")&&(o.data=o.data.replace(yb,"+")):(n=o.url.slice(f.length),o.data&&(f+=(sb.test(f)?"&":"?")+o.data,delete o.data),o.cache===!1&&(f=f.replace(Ab,""),n=(sb.test(f)?"&":"?")+"_="+rb++ +n),o.url=f+n),o.ifModified&&(r.lastModified[f]&&y.setRequestHeader("If-Modified-Since",r.lastModified[f]),r.etag[f]&&y.setRequestHeader("If-None-Match",r.etag[f])),(o.data&&o.hasContent&&o.contentType!==!1||c.contentType)&&y.setRequestHeader("Content-Type",o.contentType),y.setRequestHeader("Accept",o.dataTypes[0]&&o.accepts[o.dataTypes[0]]?o.accepts[o.dataTypes[0]]+("*"!==o.dataTypes[0]?", "+Hb+"; q=0.01":""):o.accepts["*"]);for(m in o.headers)y.setRequestHeader(m,o.headers[m]);if(o.beforeSend&&(o.beforeSend.call(p,y,o)===!1||k))return y.abort();if(x="abort",t.add(o.complete),y.done(o.success),y.fail(o.error),e=Kb(Gb,o,c,y)){if(y.readyState=1,l&&q.trigger("ajaxSend",[y,o]),k)return y;o.async&&o.timeout>0&&(i=a.setTimeout(function(){y.abort("timeout")},o.timeout));try{k=!1,e.send(v,A)}catch(z){if(k)throw z;A(-1,z)}}else A(-1,"No Transport");function A(b,c,d,h){var j,m,n,v,w,x=c;k||(k=!0,i&&a.clearTimeout(i),e=void 0,g=h||"",y.readyState=b>0?4:0,j=b>=200&&b<300||304===b,d&&(v=Mb(o,y,d)),v=Nb(o,v,y,j),j?(o.ifModified&&(w=y.getResponseHeader("Last-Modified"),w&&(r.lastModified[f]=w),w=y.getResponseHeader("etag"),w&&(r.etag[f]=w)),204===b||"HEAD"===o.type?x="nocontent":304===b?x="notmodified":(x=v.state,m=v.data,n=v.error,j=!n)):(n=x,!b&&x||(x="error",b<0&&(b=0))),y.status=b,y.statusText=(c||x)+"",j?s.resolveWith(p,[m,x,y]):s.rejectWith(p,[y,x,n]),y.statusCode(u),u=void 0,l&&q.trigger(j?"ajaxSuccess":"ajaxError",[y,o,j?m:n]),t.fireWith(p,[y,x]),l&&(q.trigger("ajaxComplete",[y,o]),--r.active||r.event.trigger("ajaxStop")))}return y},getJSON:function(a,b,c){return r.get(a,b,c,"json")},getScript:function(a,b){return r.get(a,void 0,b,"script")}}),r.each(["get","post"],function(a,b){r[b]=function(a,c,d,e){return r.isFunction(c)&&(e=e||d,d=c,c=void 0),r.ajax(r.extend({url:a,type:b,dataType:e,data:c,success:d},r.isPlainObject(a)&&a))}}),r._evalUrl=function(a){return r.ajax({url:a,type:"GET",dataType:"script",cache:!0,async:!1,global:!1,"throws":!0})},r.fn.extend({wrapAll:function(a){var b;return this[0]&&(r.isFunction(a)&&(a=a.call(this[0])),b=r(a,this[0].ownerDocument).eq(0).clone(!0),this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstElementChild)a=a.firstElementChild;return a}).append(this)),this},wrapInner:function(a){return r.isFunction(a)?this.each(function(b){r(this).wrapInner(a.call(this,b))}):this.each(function(){var b=r(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){var b=r.isFunction(a);return this.each(function(c){r(this).wrapAll(b?a.call(this,c):a)})},unwrap:function(a){return this.parent(a).not("body").each(function(){r(this).replaceWith(this.childNodes)}),this}}),r.expr.pseudos.hidden=function(a){return!r.expr.pseudos.visible(a)},r.expr.pseudos.visible=function(a){return!!(a.offsetWidth||a.offsetHeight||a.getClientRects().length)},r.ajaxSettings.xhr=function(){try{return new a.XMLHttpRequest}catch(b){}};var Ob={0:200,1223:204},Pb=r.ajaxSettings.xhr();o.cors=!!Pb&&"withCredentials"in Pb,o.ajax=Pb=!!Pb,r.ajaxTransport(function(b){var c,d;if(o.cors||Pb&&!b.crossDomain)return{send:function(e,f){var g,h=b.xhr();if(h.open(b.type,b.url,b.async,b.username,b.password),b.xhrFields)for(g in b.xhrFields)h[g]=b.xhrFields[g];b.mimeType&&h.overrideMimeType&&h.overrideMimeType(b.mimeType),b.crossDomain||e["X-Requested-With"]||(e["X-Requested-With"]="XMLHttpRequest");for(g in e)h.setRequestHeader(g,e[g]);c=function(a){return function(){c&&(c=d=h.onload=h.onerror=h.onabort=h.onreadystatechange=null,"abort"===a?h.abort():"error"===a?"number"!=typeof h.status?f(0,"error"):f(h.status,h.statusText):f(Ob[h.status]||h.status,h.statusText,"text"!==(h.responseType||"text")||"string"!=typeof h.responseText?{binary:h.response}:{text:h.responseText},h.getAllResponseHeaders()))}},h.onload=c(),d=h.onerror=c("error"),void 0!==h.onabort?h.onabort=d:h.onreadystatechange=function(){4===h.readyState&&a.setTimeout(function(){c&&d()})},c=c("abort");try{h.send(b.hasContent&&b.data||null)}catch(i){if(c)throw i}},abort:function(){c&&c()}}}),r.ajaxPrefilter(function(a){a.crossDomain&&(a.contents.script=!1)}),r.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/\b(?:java|ecma)script\b/},converters:{"text script":function(a){return r.globalEval(a),a}}}),r.ajaxPrefilter("script",function(a){void 0===a.cache&&(a.cache=!1),a.crossDomain&&(a.type="GET")}),r.ajaxTransport("script",function(a){if(a.crossDomain){var b,c;return{send:function(e,f){b=r("