├── .gitmodules ├── .travis.yml ├── Gruntfile.coffee ├── History.md ├── LICENSE ├── README.md ├── bower.json ├── lib ├── x18n.coffee ├── x18n.js └── x18n_build.js ├── package.json ├── spec ├── helper.js ├── index.html ├── spec.coffee ├── spec.js └── vendor │ ├── chai.js │ ├── jquery.js │ ├── mocha.css │ └── mocha.js └── testem.yml /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "lib/observable"] 2 | path = lib/observable 3 | url = git://github.com/florian/observable.git 4 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: [4.1.1] 3 | -------------------------------------------------------------------------------- /Gruntfile.coffee: -------------------------------------------------------------------------------- 1 | module.exports = (grunt) -> 2 | 3 | grunt.initConfig 4 | coffee: 5 | compile: 6 | files: 7 | 'lib/x18n.js': 'lib/x18n.coffee' 8 | 'spec/spec.js': 'spec/spec.coffee' 9 | 10 | concat: 11 | options: 12 | banner: '// ' + grunt.file.read('LICENSE').split("\n")[0] + "\n" 13 | stripBanners: true 14 | dist: 15 | src: ['', 'node_modules/observable_js/lib/observable.js', 'lib/x18n.js'] 16 | dest: 'lib/x18n_build.js' 17 | 18 | mocha: 19 | all: 20 | src: 'spec/index.html' 21 | run: true 22 | 23 | watch: 24 | files: ['lib/x18n.coffee', 'spec/spec.coffee'] 25 | tasks: 'release' 26 | 27 | grunt.loadNpmTasks('grunt-contrib-watch') 28 | grunt.loadNpmTasks('grunt-contrib-coffee') 29 | grunt.loadNpmTasks('grunt-mocha') 30 | grunt.loadNpmTasks('grunt-contrib-concat') 31 | 32 | grunt.registerTask('test', 'mocha') 33 | grunt.registerTask('release', ['coffee', 'concat']) 34 | grunt.registerTask('default', 'release') 35 | -------------------------------------------------------------------------------- /History.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | # 2.0.0 / 2016-04-25 4 | 5 | This is a major update with some incompatible changes: 6 | - `window.t` is no longer available per default. It's easy to get back if you 7 | want it to: 'window.t = x18n.t' 8 | - Dynamic data bindings were removed 9 | - Upgrade to Observable v2.0.0 which makes the event system a lot more stable 10 | and predictable. However this also changed how `.off` works 11 | 12 | Other changes: 13 | - It's now suggested to use NPM. There's still a browser/AMD build available in 14 | the `lib` folder though 15 | - Fixed some bugs 16 | 17 | ## 1.0.3 / 2013-03-12 18 | 19 | Upgrade to observable v1.2.1 which fixes a bug in IE. 20 | 21 | ## 1.0.2 / 2013-02-16 22 | 23 | Fix multiple implicit interpolations. 24 | 25 | ## 1.0.1 / 2013-01-25 26 | 27 | Fix AMD. Remove CommonJS for now. 28 | 29 | ## 1.0.0 / 2012-12-22 30 | 31 | Initial x18n release. 32 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2012-2016 Florian Hartmann, https://github.com/florian/x18n 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining 4 | a copy of this software and associated documentation files (the 5 | "Software"), to deal in the Software without restriction, including 6 | without limitation the rights to use, copy, modify, merge, publish, 7 | distribute, sublicense, and/or sell copies of the Software, and to 8 | permit persons to whom the Software is furnished to do so, subject to 9 | the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be 12 | included in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # X18n [![Build Status](https://travis-ci.org/florian/x18n.png)](https://travis-ci.org/florian/x18n) 2 | 3 | X18n is a JavaScript library that helps you to translate web apps that do a lot on the client side. It automatically detects the user language and sorts the available translations smartly. It has nice interpolation and pluralisation features that are also compatible with Ruby's [r18n](https://github.com/ai/r18n) gem. 4 | 5 | If you use React it's super easy to translate your app using [react-x18n](https://github.com/marco-a/react-x18n). 6 | 7 | ## Overview 8 | 9 | `npm install x18n` or just grab [x18n_build.js](https://raw.githubusercontent.com/florian/x18n/master/lib/x18n_build.js) 10 | 11 | ```js 12 | x18n.register('en', { 13 | user: { 14 | greeting: 'Welcome %1', 15 | browser: 'You are using %{browser}.', 16 | logout: 'Logout', 17 | count: { 18 | 1: 'There is 1 user online.', 19 | n: 'There are %1 users online.' 20 | } 21 | } 22 | }); 23 | 24 | let t = x18n.t; 25 | t('user.logout'); // 'Logout' 26 | t('user.greeting', 'John'); // 'Welcome John' 27 | t('user.browser', {browser: 'Chromium'}); // 'You are using Chromium.' 28 | 29 | t('user.count').plural(1); // 'There is 1 user online.' 30 | t('user.count').plural(2); // 'There are 2 users online.' 31 | 32 | x18n.on(['lang:change', 'dict:change'], function () { 33 | // Update the UI 34 | }); 35 | ``` 36 | 37 | ## Features 38 | 39 | - Auto detects the user language. 40 | - Straightforward interpolation and pluralisation. 41 | - Super easy to use with React 42 | - If you don't use React: An event system that enables you to easily re-render the UI when new translations are added or the language changes. 43 | - If a translation is missing x18n will choose a translation from a similiar locale, will save missing translations in an accessible object and will fire an event. 44 | - [r18n](https://github.com/ai/r18n) compatible interpolation and pluralisation: All you need to do to use your r18n local dictionaries in x18n is to convert them from YAML to JSON and to register the objects. 45 | 46 | ## Wiki entries 47 | 48 | - **[Getting started](https://github.com/florian/x18n/wiki/Getting-started)** 49 | - [Dealing with missing translations](https://github.com/florian/x18n/wiki/Dealing-with-missing-translations) 50 | - [Using a library that defines `window.t` together with x18n](https://github.com/florian/x18n/wiki/t.noConflict) 51 | 52 | ## Adapters 53 | 54 | X18n has no opinion about views. Because of this the x18n core stays small. Adapters are x18n extensions that are responsible for updating the view when translations change. 55 | 56 | The idea is that you are only responsible for registering translations, optionaly defining the user's language and adding data bindings to your HTML elements. The adapter will then update your HTML whenever the language changes or the dictionary is updated. 57 | 58 | Currently there are adapters available for: 59 | 60 | - [React](https://github.com/marco-a/react-x18n) (*recommended*) 61 | - [Handlebars](https://github.com/SBoudrias/handlebars-x18n) 62 | - [jQuery](https://github.com/florian/jQuery.x18n/) 63 | 64 | ## TypeScript 65 | 66 | There's a TypeScript adapter available at [anwfr/x18n-ts](https://github.com/anwfr/x18n-ts). 67 | -------------------------------------------------------------------------------- /bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "x18n", 3 | "version": "2.0.0", 4 | "homepage": "https://github.com/js-coder/x18n", 5 | "main": "lib/x18n_build.js", 6 | "ignore": [ 7 | "**/.*", 8 | "**/*.coffee", 9 | "grunt.js", 10 | "History.md", 11 | "node_modules", 12 | "bower_components", 13 | "spec", 14 | "testem.yml" 15 | ] 16 | } 17 | -------------------------------------------------------------------------------- /lib/x18n.coffee: -------------------------------------------------------------------------------- 1 | base = (Observable) -> 2 | class X18n extends Observable 3 | constructor: -> 4 | super() 5 | 6 | @dict = {} 7 | @defaultlocal = 'en' 8 | @chosenLocal = undefined 9 | 10 | @availableLocales = [] 11 | @locales = [] 12 | 13 | @missingTranslations = {} 14 | 15 | @on 'dict:change', => @sortLocales() 16 | 17 | utils: 18 | merge: (one, two) -> 19 | for k, v of two 20 | if typeof v is 'object' and typeof one[k] is 'object' 21 | @merge(one[k], v) 22 | else 23 | one[k] = v 24 | 25 | filter: (arr, fn) -> 26 | v for v in arr when fn(v) 27 | 28 | unique: (arr) -> 29 | ret = {} 30 | ret[v] = v for v in arr 31 | v for k, v of ret 32 | 33 | getByDotNotation: (obj, key) -> 34 | keys = key.split('.') 35 | 36 | until keys.length is 0 or obj is undefined 37 | obj = obj[keys[0]] 38 | keys.shift() 39 | 40 | obj 41 | 42 | isPlainObject: (value) -> 43 | !!value && Object::toString.call(value) is '[object Object]' 44 | 45 | register: (local, dict) -> 46 | unless local of @dict 47 | @dict[local] = {} 48 | @availableLocales.push(local) 49 | 50 | @utils.merge(@dict[local], dict) 51 | 52 | @trigger('dict:change', [local]) 53 | 54 | set: (local) -> 55 | @chosenLocal = local 56 | @sortLocales() 57 | 58 | setDefault: (local) -> 59 | @defaultLocal = local 60 | @sortLocales() 61 | 62 | # Todo: This would throw on node 63 | detectLocal: -> navigator.userLanguage || navigator.language 64 | 65 | similiarLocales: (local) -> 66 | local = String(local).slice(0, 2).toLowerCase() 67 | @utils.filter @availableLocales, (l) -> 68 | return false if local is l 69 | l.toLowerCase().indexOf(local) is 0 70 | 71 | sortLocales: -> 72 | oldLocales = @locales.slice() 73 | 74 | _locales = [ 75 | @chosenLocal 76 | @similiarLocales(@chosenLocal)... 77 | @detectLocal(), 78 | @similiarLocales(@detectLocal())... 79 | @defaultLocal, 80 | @similiarLocales(@defaultlocal)... 81 | 'en' 82 | @similiarLocales('en')..., 83 | ] 84 | 85 | locales = [] 86 | locales.push(local) for local in _locales when local in @availableLocales 87 | 88 | locales.push(@availableLocales...) 89 | 90 | @locales = @utils.unique(locales) 91 | 92 | if oldLocales.join(',') isnt @locales.join(',') 93 | @trigger('lang:change', [@locales, oldLocales]) 94 | 95 | interpolate: (str, interpolation...) -> 96 | if @utils.isPlainObject(interpolation[0]) 97 | str = str.replace /%\{([^}]+)\}/g, (_, key) -> 98 | interpolation[0][key] 99 | else 100 | str = str.replace /%(\d+)/g, (_, n) -> 101 | interpolation[Number(n) - 1] 102 | 103 | str 104 | 105 | t: (key, interpolation...) => 106 | tr = undefined 107 | for local in @locales 108 | tr = @utils.getByDotNotation(@dict[local], key) 109 | if tr 110 | break 111 | else 112 | @missingTranslations[local] = [] unless local of @missingTranslations 113 | @missingTranslations[local].push(key) 114 | @missingTranslations[local] = @utils.unique(@missingTranslations[local]) 115 | @trigger('missing-translation', [local, key]) 116 | 117 | if typeof tr is 'string' 118 | tr = @interpolate(tr, interpolation...) 119 | else if tr isnt undefined 120 | tr.plural = (n) => 121 | if n of tr 122 | tr[n] 123 | else 124 | @interpolate(tr.n, n) 125 | 126 | tr 127 | 128 | return new X18n() 129 | 130 | if module? and module.exports? 131 | Observable = require('observable_js') 132 | module.exports = base(Observable) 133 | else if typeof define is 'function' and define.amd 134 | define 'x18n', ['observable_js'], (Observable) -> base(Observable) 135 | else 136 | window.x18n = base(window.Observable) 137 | -------------------------------------------------------------------------------- /lib/x18n.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | var Observable, base, 3 | bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }, 4 | extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }, 5 | hasProp = {}.hasOwnProperty, 6 | slice = [].slice, 7 | indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }; 8 | 9 | base = function(Observable) { 10 | var X18n; 11 | X18n = (function(superClass) { 12 | extend(X18n, superClass); 13 | 14 | function X18n() { 15 | this.t = bind(this.t, this); 16 | X18n.__super__.constructor.call(this); 17 | this.dict = {}; 18 | this.defaultlocal = 'en'; 19 | this.chosenLocal = void 0; 20 | this.availableLocales = []; 21 | this.locales = []; 22 | this.missingTranslations = {}; 23 | this.on('dict:change', (function(_this) { 24 | return function() { 25 | return _this.sortLocales(); 26 | }; 27 | })(this)); 28 | } 29 | 30 | X18n.prototype.utils = { 31 | merge: function(one, two) { 32 | var k, results, v; 33 | results = []; 34 | for (k in two) { 35 | v = two[k]; 36 | if (typeof v === 'object' && typeof one[k] === 'object') { 37 | results.push(this.merge(one[k], v)); 38 | } else { 39 | results.push(one[k] = v); 40 | } 41 | } 42 | return results; 43 | }, 44 | filter: function(arr, fn) { 45 | var i, len, results, v; 46 | results = []; 47 | for (i = 0, len = arr.length; i < len; i++) { 48 | v = arr[i]; 49 | if (fn(v)) { 50 | results.push(v); 51 | } 52 | } 53 | return results; 54 | }, 55 | unique: function(arr) { 56 | var i, k, len, results, ret, v; 57 | ret = {}; 58 | for (i = 0, len = arr.length; i < len; i++) { 59 | v = arr[i]; 60 | ret[v] = v; 61 | } 62 | results = []; 63 | for (k in ret) { 64 | v = ret[k]; 65 | results.push(v); 66 | } 67 | return results; 68 | }, 69 | getByDotNotation: function(obj, key) { 70 | var keys; 71 | keys = key.split('.'); 72 | while (!(keys.length === 0 || obj === void 0)) { 73 | obj = obj[keys[0]]; 74 | keys.shift(); 75 | } 76 | return obj; 77 | }, 78 | isPlainObject: function(value) { 79 | return !!value && Object.prototype.toString.call(value) === '[object Object]'; 80 | } 81 | }; 82 | 83 | X18n.prototype.register = function(local, dict) { 84 | if (!(local in this.dict)) { 85 | this.dict[local] = {}; 86 | this.availableLocales.push(local); 87 | } 88 | this.utils.merge(this.dict[local], dict); 89 | return this.trigger('dict:change', [local]); 90 | }; 91 | 92 | X18n.prototype.set = function(local) { 93 | this.chosenLocal = local; 94 | return this.sortLocales(); 95 | }; 96 | 97 | X18n.prototype.setDefault = function(local) { 98 | this.defaultLocal = local; 99 | return this.sortLocales(); 100 | }; 101 | 102 | X18n.prototype.detectLocal = function() { 103 | return navigator.userLanguage || navigator.language; 104 | }; 105 | 106 | X18n.prototype.similiarLocales = function(local) { 107 | local = String(local).slice(0, 2).toLowerCase(); 108 | return this.utils.filter(this.availableLocales, function(l) { 109 | if (local === l) { 110 | return false; 111 | } 112 | return l.toLowerCase().indexOf(local) === 0; 113 | }); 114 | }; 115 | 116 | X18n.prototype.sortLocales = function() { 117 | var _locales, i, len, local, locales, oldLocales; 118 | oldLocales = this.locales.slice(); 119 | _locales = [this.chosenLocal].concat(slice.call(this.similiarLocales(this.chosenLocal)), [this.detectLocal()], slice.call(this.similiarLocales(this.detectLocal())), [this.defaultLocal], slice.call(this.similiarLocales(this.defaultlocal)), ['en'], slice.call(this.similiarLocales('en'))); 120 | locales = []; 121 | for (i = 0, len = _locales.length; i < len; i++) { 122 | local = _locales[i]; 123 | if (indexOf.call(this.availableLocales, local) >= 0) { 124 | locales.push(local); 125 | } 126 | } 127 | locales.push.apply(locales, this.availableLocales); 128 | this.locales = this.utils.unique(locales); 129 | if (oldLocales.join(',') !== this.locales.join(',')) { 130 | return this.trigger('lang:change', [this.locales, oldLocales]); 131 | } 132 | }; 133 | 134 | X18n.prototype.interpolate = function() { 135 | var interpolation, str; 136 | str = arguments[0], interpolation = 2 <= arguments.length ? slice.call(arguments, 1) : []; 137 | if (this.utils.isPlainObject(interpolation[0])) { 138 | str = str.replace(/%\{([^}]+)\}/g, function(_, key) { 139 | return interpolation[0][key]; 140 | }); 141 | } else { 142 | str = str.replace(/%(\d+)/g, function(_, n) { 143 | return interpolation[Number(n) - 1]; 144 | }); 145 | } 146 | return str; 147 | }; 148 | 149 | X18n.prototype.t = function() { 150 | var i, interpolation, key, len, local, ref, tr; 151 | key = arguments[0], interpolation = 2 <= arguments.length ? slice.call(arguments, 1) : []; 152 | tr = void 0; 153 | ref = this.locales; 154 | for (i = 0, len = ref.length; i < len; i++) { 155 | local = ref[i]; 156 | tr = this.utils.getByDotNotation(this.dict[local], key); 157 | if (tr) { 158 | break; 159 | } else { 160 | if (!(local in this.missingTranslations)) { 161 | this.missingTranslations[local] = []; 162 | } 163 | this.missingTranslations[local].push(key); 164 | this.missingTranslations[local] = this.utils.unique(this.missingTranslations[local]); 165 | this.trigger('missing-translation', [local, key]); 166 | } 167 | } 168 | if (typeof tr === 'string') { 169 | tr = this.interpolate.apply(this, [tr].concat(slice.call(interpolation))); 170 | } else if (tr !== void 0) { 171 | tr.plural = (function(_this) { 172 | return function(n) { 173 | if (n in tr) { 174 | return tr[n]; 175 | } else { 176 | return _this.interpolate(tr.n, n); 177 | } 178 | }; 179 | })(this); 180 | } 181 | return tr; 182 | }; 183 | 184 | return X18n; 185 | 186 | })(Observable); 187 | return new X18n(); 188 | }; 189 | 190 | if ((typeof module !== "undefined" && module !== null) && (module.exports != null)) { 191 | Observable = require('observable_js'); 192 | module.exports = base(Observable); 193 | } else if (typeof define === 'function' && define.amd) { 194 | define('x18n', ['observable_js'], function(Observable) { 195 | return base(Observable); 196 | }); 197 | } else { 198 | window.x18n = base(window.Observable); 199 | } 200 | 201 | }).call(this); 202 | -------------------------------------------------------------------------------- /lib/x18n_build.js: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2012-2016 Florian Hartmann, https://github.com/florian/x18n 2 | // Copyright (c) 2012-2016 Florian Hartmann, https://github.com/florian/observable 3 | (function() { 4 | var Observable, isPlainObject, isType, toArray; 5 | 6 | isType = function(type, value) { 7 | return Object.prototype.toString.call(value).match(/\s(\w+)/)[1].toLowerCase() === type; 8 | }; 9 | 10 | isPlainObject = function(value) { 11 | return !!value && isType('object', value); 12 | }; 13 | 14 | toArray = function(value) { 15 | if (isType('array', value)) { 16 | return value; 17 | } else { 18 | return [value]; 19 | } 20 | }; 21 | 22 | Observable = (function() { 23 | function Observable() { 24 | this.__eventStore = {}; 25 | this.__asyncEvents = true; 26 | } 27 | 28 | Observable.mixin = function(host) { 29 | var fn, key, ref, results; 30 | host.__eventStore = {}; 31 | ref = Observable.prototype; 32 | results = []; 33 | for (key in ref) { 34 | fn = ref[key]; 35 | results.push(host[key] = fn); 36 | } 37 | return results; 38 | }; 39 | 40 | Observable.prototype.on = function(topics, fn, once) { 41 | var base, i, len, ref, topic; 42 | if (once == null) { 43 | once = false; 44 | } 45 | if (isPlainObject(topics)) { 46 | for (topic in topics) { 47 | fn = topics[topic]; 48 | this.on(topic, fn); 49 | } 50 | } else { 51 | ref = toArray(topics); 52 | for (i = 0, len = ref.length; i < len; i++) { 53 | topic = ref[i]; 54 | (base = this.__eventStore)[topic] || (base[topic] = []); 55 | this.__eventStore[topic].push({ 56 | fn: fn, 57 | once: once 58 | }); 59 | } 60 | } 61 | return this; 62 | }; 63 | 64 | Observable.prototype.once = function(topics, fn) { 65 | if (fn) { 66 | return this.on(topics, fn, true); 67 | } else { 68 | return this.on(topics, true); 69 | } 70 | }; 71 | 72 | Observable.prototype.off = function(topics, fn) { 73 | var i, j, len, len1, ref, ref1, topic; 74 | if (!fn) { 75 | ref = toArray(topics); 76 | for (i = 0, len = ref.length; i < len; i++) { 77 | topic = ref[i]; 78 | this.__eventStore[topic] = []; 79 | } 80 | } 81 | if (isPlainObject(topics)) { 82 | for (topic in topics) { 83 | fn = topics[topic]; 84 | this.off(topic, fn); 85 | } 86 | } else { 87 | ref1 = toArray(topics); 88 | for (j = 0, len1 = ref1.length; j < len1; j++) { 89 | topic = ref1[j]; 90 | this.__eventStore[topic] = (this.__eventStore[topic] || []).filter(function(subscriber) { 91 | return subscriber.fn !== fn; 92 | }); 93 | } 94 | } 95 | return this; 96 | }; 97 | 98 | Observable.prototype.trigger = function(topic, args) { 99 | var ref; 100 | args || (args = []); 101 | if ((ref = this.__eventStore[topic]) != null) { 102 | ref.forEach((function(_this) { 103 | return function(arg) { 104 | var fn, once; 105 | fn = arg.fn, once = arg.once; 106 | if (_this.__asyncEvents) { 107 | setTimeout((function() { 108 | return fn.apply(null, args); 109 | }), 1); 110 | } else { 111 | fn.apply(null, args); 112 | } 113 | if (once) { 114 | return _this.off(topic, fn); 115 | } 116 | }; 117 | })(this)); 118 | } 119 | return this; 120 | }; 121 | 122 | return Observable; 123 | 124 | })(); 125 | 126 | if (typeof define === 'function' && define.amd) { 127 | define('observable', [], function() { 128 | return Observable; 129 | }); 130 | } else if (typeof exports !== 'undefined') { 131 | module.exports = Observable; 132 | } else { 133 | window.Observable = Observable; 134 | } 135 | 136 | }).call(this); 137 | 138 | (function() { 139 | var Observable, base, 140 | bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }, 141 | extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }, 142 | hasProp = {}.hasOwnProperty, 143 | slice = [].slice, 144 | indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }; 145 | 146 | base = function(Observable) { 147 | var X18n; 148 | X18n = (function(superClass) { 149 | extend(X18n, superClass); 150 | 151 | function X18n() { 152 | this.t = bind(this.t, this); 153 | X18n.__super__.constructor.call(this); 154 | this.dict = {}; 155 | this.defaultlocal = 'en'; 156 | this.chosenLocal = void 0; 157 | this.availableLocales = []; 158 | this.locales = []; 159 | this.missingTranslations = {}; 160 | this.on('dict:change', (function(_this) { 161 | return function() { 162 | return _this.sortLocales(); 163 | }; 164 | })(this)); 165 | } 166 | 167 | X18n.prototype.utils = { 168 | merge: function(one, two) { 169 | var k, results, v; 170 | results = []; 171 | for (k in two) { 172 | v = two[k]; 173 | if (typeof v === 'object' && typeof one[k] === 'object') { 174 | results.push(this.merge(one[k], v)); 175 | } else { 176 | results.push(one[k] = v); 177 | } 178 | } 179 | return results; 180 | }, 181 | filter: function(arr, fn) { 182 | var i, len, results, v; 183 | results = []; 184 | for (i = 0, len = arr.length; i < len; i++) { 185 | v = arr[i]; 186 | if (fn(v)) { 187 | results.push(v); 188 | } 189 | } 190 | return results; 191 | }, 192 | unique: function(arr) { 193 | var i, k, len, results, ret, v; 194 | ret = {}; 195 | for (i = 0, len = arr.length; i < len; i++) { 196 | v = arr[i]; 197 | ret[v] = v; 198 | } 199 | results = []; 200 | for (k in ret) { 201 | v = ret[k]; 202 | results.push(v); 203 | } 204 | return results; 205 | }, 206 | getByDotNotation: function(obj, key) { 207 | var keys; 208 | keys = key.split('.'); 209 | while (!(keys.length === 0 || obj === void 0)) { 210 | obj = obj[keys[0]]; 211 | keys.shift(); 212 | } 213 | return obj; 214 | }, 215 | isPlainObject: function(value) { 216 | return !!value && Object.prototype.toString.call(value) === '[object Object]'; 217 | } 218 | }; 219 | 220 | X18n.prototype.register = function(local, dict) { 221 | if (!(local in this.dict)) { 222 | this.dict[local] = {}; 223 | this.availableLocales.push(local); 224 | } 225 | this.utils.merge(this.dict[local], dict); 226 | return this.trigger('dict:change', [local]); 227 | }; 228 | 229 | X18n.prototype.set = function(local) { 230 | this.chosenLocal = local; 231 | return this.sortLocales(); 232 | }; 233 | 234 | X18n.prototype.setDefault = function(local) { 235 | this.defaultLocal = local; 236 | return this.sortLocales(); 237 | }; 238 | 239 | X18n.prototype.detectLocal = function() { 240 | return navigator.userLanguage || navigator.language; 241 | }; 242 | 243 | X18n.prototype.similiarLocales = function(local) { 244 | local = String(local).slice(0, 2).toLowerCase(); 245 | return this.utils.filter(this.availableLocales, function(l) { 246 | if (local === l) { 247 | return false; 248 | } 249 | return l.toLowerCase().indexOf(local) === 0; 250 | }); 251 | }; 252 | 253 | X18n.prototype.sortLocales = function() { 254 | var _locales, i, len, local, locales, oldLocales; 255 | oldLocales = this.locales.slice(); 256 | _locales = [this.chosenLocal].concat(slice.call(this.similiarLocales(this.chosenLocal)), [this.detectLocal()], slice.call(this.similiarLocales(this.detectLocal())), [this.defaultLocal], slice.call(this.similiarLocales(this.defaultlocal)), ['en'], slice.call(this.similiarLocales('en'))); 257 | locales = []; 258 | for (i = 0, len = _locales.length; i < len; i++) { 259 | local = _locales[i]; 260 | if (indexOf.call(this.availableLocales, local) >= 0) { 261 | locales.push(local); 262 | } 263 | } 264 | locales.push.apply(locales, this.availableLocales); 265 | this.locales = this.utils.unique(locales); 266 | if (oldLocales.join(',') !== this.locales.join(',')) { 267 | return this.trigger('lang:change', [this.locales, oldLocales]); 268 | } 269 | }; 270 | 271 | X18n.prototype.interpolate = function() { 272 | var interpolation, str; 273 | str = arguments[0], interpolation = 2 <= arguments.length ? slice.call(arguments, 1) : []; 274 | if (this.utils.isPlainObject(interpolation[0])) { 275 | str = str.replace(/%\{([^}]+)\}/g, function(_, key) { 276 | return interpolation[0][key]; 277 | }); 278 | } else { 279 | str = str.replace(/%(\d+)/g, function(_, n) { 280 | return interpolation[Number(n) - 1]; 281 | }); 282 | } 283 | return str; 284 | }; 285 | 286 | X18n.prototype.t = function() { 287 | var i, interpolation, key, len, local, ref, tr; 288 | key = arguments[0], interpolation = 2 <= arguments.length ? slice.call(arguments, 1) : []; 289 | tr = void 0; 290 | ref = this.locales; 291 | for (i = 0, len = ref.length; i < len; i++) { 292 | local = ref[i]; 293 | tr = this.utils.getByDotNotation(this.dict[local], key); 294 | if (tr) { 295 | break; 296 | } else { 297 | if (!(local in this.missingTranslations)) { 298 | this.missingTranslations[local] = []; 299 | } 300 | this.missingTranslations[local].push(key); 301 | this.missingTranslations[local] = this.utils.unique(this.missingTranslations[local]); 302 | this.trigger('missing-translation', [local, key]); 303 | } 304 | } 305 | if (typeof tr === 'string') { 306 | tr = this.interpolate.apply(this, [tr].concat(slice.call(interpolation))); 307 | } else if (tr !== void 0) { 308 | tr.plural = (function(_this) { 309 | return function(n) { 310 | if (n in tr) { 311 | return tr[n]; 312 | } else { 313 | return _this.interpolate(tr.n, n); 314 | } 315 | }; 316 | })(this); 317 | } 318 | return tr; 319 | }; 320 | 321 | return X18n; 322 | 323 | })(Observable); 324 | return new X18n(); 325 | }; 326 | 327 | if ((typeof module !== "undefined" && module !== null) && (module.exports != null)) { 328 | Observable = require('observable_js'); 329 | module.exports = base(Observable); 330 | } else if (typeof define === 'function' && define.amd) { 331 | define('x18n', ['observable_js'], function(Observable) { 332 | return base(Observable); 333 | }); 334 | } else { 335 | window.x18n = base(window.Observable); 336 | } 337 | 338 | }).call(this); 339 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "x18n", 3 | "version": "2.0.3", 4 | "description": "A JavaScript internationalisation library", 5 | "github": "https://github.com/florian/x18n", 6 | "license": "MIT", 7 | "main": "lib/x18n_build.js", 8 | "scripts": { 9 | "test": "grunt test" 10 | }, 11 | "repository": { 12 | "type": "git", 13 | "url": "http://github.com/florian/x18n.git" 14 | }, 15 | "bugs": { 16 | "url": "http://github.com/florian/x18n/issues" 17 | }, 18 | "dependencies": { 19 | "observable_js": "^2.0.1" 20 | }, 21 | "devDependencies": { 22 | "grunt": "^1.0.1", 23 | "grunt-contrib-coffee": "^1.0.0", 24 | "grunt-contrib-concat": "^1.0.0", 25 | "grunt-contrib-watch": "^1.0.0", 26 | "grunt-mocha": "^1.0.1" 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /spec/helper.js: -------------------------------------------------------------------------------- 1 | // testem 2 | if (location.href.indexOf('http://localhost:1221') == 0) { 3 | document.write(' 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /spec/spec.coffee: -------------------------------------------------------------------------------- 1 | utils = x18n.utils 2 | dict = x18n.dict 3 | t = x18n.t 4 | 5 | # Observable triggers events async by default, which makes it harder to write 6 | # tests, so we'll disable it 7 | x18n.__asyncEvents = false 8 | 9 | describe 'x18n', -> 10 | afterEach -> 11 | dict = x18n.dict = {} 12 | x18n.chosenLocal = undefined 13 | x18n.defaultLocal = 'en' 14 | x18n.availableLocales = [] 15 | x18n.sortLocales() 16 | 17 | describe 'utils', -> 18 | describe 'merge', -> 19 | it 'should be able to merge a single object', -> 20 | a = a: 1 21 | b = b: 2 22 | utils.merge(a, b) 23 | expect(a).to.eql(a: 1, b: 2) 24 | 25 | it 'should be able to deep merge objects', -> 26 | a = a: a: 1 27 | b = a: b: 2 28 | utils.merge(a: a: 1, b: 2) 29 | 30 | describe 'filter', -> 31 | it 'should return an array with the filtered values', -> 32 | a = [1..9] 33 | a = utils.filter a, (n) -> n % 2 == 0 34 | expect(a).to.eql([2, 4, 6, 8]) 35 | 36 | describe 'unique', -> 37 | it 'should remove duplicate entries', -> 38 | a = utils.unique([1, 2, 1, 3, 1, 2]) 39 | expect(a).to.eql([1, 2, 3]) 40 | 41 | describe 'getByDotNotation', -> 42 | it 'should return the specified value', -> 43 | v = utils.getByDotNotation({a: b: c: 1}, 'a.b.c') 44 | expect(v).to.equal(1) 45 | 46 | it 'should never throw an error', -> 47 | fn = -> 48 | utils.getByDotNotation(a: 1, 'b.c') 49 | expect(fn).not.to.throw() 50 | 51 | describe 'event system', -> 52 | it 'should be available', -> 53 | expect(x18n.on).to.be.a('function') 54 | expect(x18n.once).to.be.a('function') 55 | expect(x18n.off).to.be.a('function') 56 | expect(x18n.trigger).to.be.a('function') 57 | 58 | describe 'register', -> 59 | it "should create a lang key in the dict if it doesn't exist", -> 60 | x18n.register 'en', {} 61 | expect(dict).to.have.property('en').that.is.an('object') 62 | 63 | it 'should fill the dict', -> 64 | x18n.register 'en', user: 'user' 65 | expect(dict.en).to.have.property('user', 'user') 66 | 67 | it 'should not replace existing properties, but merge them', -> 68 | x18n.register 'en', user: 'user' 69 | x18n.register 'en', login: 'login' 70 | expect(dict.en).to.eql(user: 'user', login: 'login') 71 | 72 | it 'should trigger the event dict:change', -> 73 | called = false 74 | x18n.on 'dict:change', -> called = true 75 | x18n.register 'en', {} 76 | expect(called).to.be.true 77 | 78 | describe 'set', -> 79 | it 'should set @chosenLocal', -> 80 | x18n.set 'de' 81 | expect(x18n.chosenLocal).to.equal('de') 82 | 83 | describe 'setDefault', -> 84 | it 'should set @defaultLocal', -> 85 | x18n.setDefault 'en' 86 | expect(x18n.defaultLocal).to.equal('en') 87 | 88 | describe 'similiarLocales', -> 89 | it 'should detect similiar locales', -> 90 | x18n.availableLocales = ['en', 'en-us', 'en-AU', 'de', 'fr'] 91 | expect(x18n.similiarLocales('en')).to.eql(['en-us', 'en-AU']) 92 | 93 | describe 'sortLocales', -> 94 | it 'should set @locales to an array', -> 95 | x18n.sortLocales() 96 | expect(x18n.locales).to.be.an('array') 97 | 98 | it 'should trigger lang:change', -> 99 | x18n.register('test', { a: 'a' }) 100 | x18n.register('en', { a: 'a' }) 101 | 102 | called = false 103 | x18n.on 'lang:change', -> called = true 104 | 105 | x18n.defaultLocal = 'test' 106 | x18n.sortLocales() 107 | 108 | expect(called).to.be.true 109 | 110 | x18n.defaultLocal = 'en' 111 | x18n.sortLocales() 112 | 113 | ### 114 | it should contain the chosen local first if set 115 | it should only contain available locales 116 | it should not contain duplicate entries 117 | ### 118 | 119 | describe 'interpolate', -> 120 | it 'should support numeric interpolation', -> 121 | s = x18n.interpolate('Hello %1', 'World') 122 | expect(s).to.equal('Hello World') 123 | 124 | it 'should support alpha interpolation', -> 125 | s = x18n.interpolate('Hello %{s}', s: 'World') 126 | expect(s).to.equal('Hello World') 127 | 128 | it 'should support several interpolations in one string', -> 129 | s = x18n.interpolate('Hello %1 and %2', 'a', 'b') 130 | expect(s).to.equal('Hello a and b') 131 | 132 | describe 't', -> 133 | it 'should be defined', -> 134 | expect(x18n).to.have.property('t') 135 | 136 | it 'should return the translation', -> 137 | x18n.register 'de', user: 'benutzer' 138 | expect(t('user')).to.equal('benutzer') 139 | 140 | it 'should loop through all available locales and return the first translation', -> 141 | x18n.register 'de', {} 142 | x18n.register 'en', user: 'user' 143 | expect(t('user')).to.equal('user') 144 | 145 | it 'should behave like utils.getByDotNotation', -> 146 | x18n.register 'en', errors: presence: 'Not found' 147 | expect(t('errors.presence')).to.equal('Not found') 148 | 149 | it "should populate @missingTranslation if the translation doesn't exist in some language", -> 150 | x18n.register 'en', {} 151 | t('register') 152 | expect(x18n.missingTranslations).to.have.property('en').that.is.an('array').that.include('register') 153 | 154 | it "should trigger the event missing-translation if the translation doesn't exist in some language", -> 155 | called = false 156 | x18n.on 'missing-translation', -> called = true 157 | x18n.register 'en', {} 158 | t('register') 159 | expect(called).to.be.true 160 | 161 | it 'should support interpolation', -> 162 | x18n.register 'en', 163 | a: 'Hello %1', 164 | 165 | expect(t('a', 'World')).to.equal('Hello World') 166 | 167 | it 'should support multiple interpolations', -> 168 | x18n.register 'en', 169 | greeting: 'Hi %1 and %2' 170 | 171 | expect(t('greeting', 'a', 'b')).to.equal('Hi a and b') 172 | 173 | it 'should support explicit interpolation', -> 174 | x18n.register 'en', 175 | a: 'Hello %{s}' 176 | 177 | expect(t('a', s: 'World')).to.equal('Hello World') 178 | 179 | it 'should return an object with a plural method when requesting a plural', -> 180 | x18n.register 'en', 181 | users: 182 | 1: 'There is 1 user online' 183 | n: 'There are %1 users online' 184 | 185 | expect(t('users')).to.have.property('plural').that.is.a('function') 186 | 187 | it 'should support pluralisation', -> 188 | x18n.register 'en', 189 | users: 190 | 1: 'There is 1 user online' 191 | n: 'There are %1 users online' 192 | 193 | expect(t('users').plural(1)).to.equal('There is 1 user online') 194 | expect(t('users').plural(3)).to.equal('There are 3 users online') 195 | -------------------------------------------------------------------------------- /spec/spec.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | var dict, t, utils; 3 | 4 | utils = x18n.utils; 5 | 6 | dict = x18n.dict; 7 | 8 | t = x18n.t; 9 | 10 | x18n.__asyncEvents = false; 11 | 12 | describe('x18n', function() { 13 | afterEach(function() { 14 | dict = x18n.dict = {}; 15 | x18n.chosenLocal = void 0; 16 | x18n.defaultLocal = 'en'; 17 | x18n.availableLocales = []; 18 | return x18n.sortLocales(); 19 | }); 20 | describe('utils', function() { 21 | describe('merge', function() { 22 | it('should be able to merge a single object', function() { 23 | var a, b; 24 | a = { 25 | a: 1 26 | }; 27 | b = { 28 | b: 2 29 | }; 30 | utils.merge(a, b); 31 | return expect(a).to.eql({ 32 | a: 1, 33 | b: 2 34 | }); 35 | }); 36 | return it('should be able to deep merge objects', function() { 37 | var a, b; 38 | a = { 39 | a: { 40 | a: 1 41 | } 42 | }; 43 | b = { 44 | a: { 45 | b: 2 46 | } 47 | }; 48 | return utils.merge({ 49 | a: { 50 | a: 1, 51 | b: 2 52 | } 53 | }); 54 | }); 55 | }); 56 | describe('filter', function() { 57 | return it('should return an array with the filtered values', function() { 58 | var a; 59 | a = [1, 2, 3, 4, 5, 6, 7, 8, 9]; 60 | a = utils.filter(a, function(n) { 61 | return n % 2 === 0; 62 | }); 63 | return expect(a).to.eql([2, 4, 6, 8]); 64 | }); 65 | }); 66 | describe('unique', function() { 67 | return it('should remove duplicate entries', function() { 68 | var a; 69 | a = utils.unique([1, 2, 1, 3, 1, 2]); 70 | return expect(a).to.eql([1, 2, 3]); 71 | }); 72 | }); 73 | return describe('getByDotNotation', function() { 74 | it('should return the specified value', function() { 75 | var v; 76 | v = utils.getByDotNotation({ 77 | a: { 78 | b: { 79 | c: 1 80 | } 81 | } 82 | }, 'a.b.c'); 83 | return expect(v).to.equal(1); 84 | }); 85 | return it('should never throw an error', function() { 86 | var fn; 87 | fn = function() { 88 | return utils.getByDotNotation({ 89 | a: 1 90 | }, 'b.c'); 91 | }; 92 | return expect(fn).not.to["throw"](); 93 | }); 94 | }); 95 | }); 96 | describe('event system', function() { 97 | return it('should be available', function() { 98 | expect(x18n.on).to.be.a('function'); 99 | expect(x18n.once).to.be.a('function'); 100 | expect(x18n.off).to.be.a('function'); 101 | return expect(x18n.trigger).to.be.a('function'); 102 | }); 103 | }); 104 | describe('register', function() { 105 | it("should create a lang key in the dict if it doesn't exist", function() { 106 | x18n.register('en', {}); 107 | return expect(dict).to.have.property('en').that.is.an('object'); 108 | }); 109 | it('should fill the dict', function() { 110 | x18n.register('en', { 111 | user: 'user' 112 | }); 113 | return expect(dict.en).to.have.property('user', 'user'); 114 | }); 115 | it('should not replace existing properties, but merge them', function() { 116 | x18n.register('en', { 117 | user: 'user' 118 | }); 119 | x18n.register('en', { 120 | login: 'login' 121 | }); 122 | return expect(dict.en).to.eql({ 123 | user: 'user', 124 | login: 'login' 125 | }); 126 | }); 127 | return it('should trigger the event dict:change', function() { 128 | var called; 129 | called = false; 130 | x18n.on('dict:change', function() { 131 | return called = true; 132 | }); 133 | x18n.register('en', {}); 134 | return expect(called).to.be["true"]; 135 | }); 136 | }); 137 | describe('set', function() { 138 | return it('should set @chosenLocal', function() { 139 | x18n.set('de'); 140 | return expect(x18n.chosenLocal).to.equal('de'); 141 | }); 142 | }); 143 | describe('setDefault', function() { 144 | return it('should set @defaultLocal', function() { 145 | x18n.setDefault('en'); 146 | return expect(x18n.defaultLocal).to.equal('en'); 147 | }); 148 | }); 149 | describe('similiarLocales', function() { 150 | return it('should detect similiar locales', function() { 151 | x18n.availableLocales = ['en', 'en-us', 'en-AU', 'de', 'fr']; 152 | return expect(x18n.similiarLocales('en')).to.eql(['en-us', 'en-AU']); 153 | }); 154 | }); 155 | describe('sortLocales', function() { 156 | it('should set @locales to an array', function() { 157 | x18n.sortLocales(); 158 | return expect(x18n.locales).to.be.an('array'); 159 | }); 160 | return it('should trigger lang:change', function() { 161 | var called; 162 | x18n.register('test', { 163 | a: 'a' 164 | }); 165 | x18n.register('en', { 166 | a: 'a' 167 | }); 168 | called = false; 169 | x18n.on('lang:change', function() { 170 | return called = true; 171 | }); 172 | x18n.defaultLocal = 'test'; 173 | x18n.sortLocales(); 174 | expect(called).to.be["true"]; 175 | x18n.defaultLocal = 'en'; 176 | return x18n.sortLocales(); 177 | }); 178 | 179 | /* 180 | it should contain the chosen local first if set 181 | it should only contain available locales 182 | it should not contain duplicate entries 183 | */ 184 | }); 185 | describe('interpolate', function() { 186 | it('should support numeric interpolation', function() { 187 | var s; 188 | s = x18n.interpolate('Hello %1', 'World'); 189 | return expect(s).to.equal('Hello World'); 190 | }); 191 | it('should support alpha interpolation', function() { 192 | var s; 193 | s = x18n.interpolate('Hello %{s}', { 194 | s: 'World' 195 | }); 196 | return expect(s).to.equal('Hello World'); 197 | }); 198 | return it('should support several interpolations in one string', function() { 199 | var s; 200 | s = x18n.interpolate('Hello %1 and %2', 'a', 'b'); 201 | return expect(s).to.equal('Hello a and b'); 202 | }); 203 | }); 204 | return describe('t', function() { 205 | it('should be defined', function() { 206 | return expect(x18n).to.have.property('t'); 207 | }); 208 | it('should return the translation', function() { 209 | x18n.register('de', { 210 | user: 'benutzer' 211 | }); 212 | return expect(t('user')).to.equal('benutzer'); 213 | }); 214 | it('should loop through all available locales and return the first translation', function() { 215 | x18n.register('de', {}); 216 | x18n.register('en', { 217 | user: 'user' 218 | }); 219 | return expect(t('user')).to.equal('user'); 220 | }); 221 | it('should behave like utils.getByDotNotation', function() { 222 | x18n.register('en', { 223 | errors: { 224 | presence: 'Not found' 225 | } 226 | }); 227 | return expect(t('errors.presence')).to.equal('Not found'); 228 | }); 229 | it("should populate @missingTranslation if the translation doesn't exist in some language", function() { 230 | x18n.register('en', {}); 231 | t('register'); 232 | return expect(x18n.missingTranslations).to.have.property('en').that.is.an('array').that.include('register'); 233 | }); 234 | it("should trigger the event missing-translation if the translation doesn't exist in some language", function() { 235 | var called; 236 | called = false; 237 | x18n.on('missing-translation', function() { 238 | return called = true; 239 | }); 240 | x18n.register('en', {}); 241 | t('register'); 242 | return expect(called).to.be["true"]; 243 | }); 244 | it('should support interpolation', function() { 245 | x18n.register('en', { 246 | a: 'Hello %1' 247 | }); 248 | return expect(t('a', 'World')).to.equal('Hello World'); 249 | }); 250 | it('should support multiple interpolations', function() { 251 | x18n.register('en', { 252 | greeting: 'Hi %1 and %2' 253 | }); 254 | return expect(t('greeting', 'a', 'b')).to.equal('Hi a and b'); 255 | }); 256 | it('should support explicit interpolation', function() { 257 | x18n.register('en', { 258 | a: 'Hello %{s}' 259 | }); 260 | return expect(t('a', { 261 | s: 'World' 262 | })).to.equal('Hello World'); 263 | }); 264 | it('should return an object with a plural method when requesting a plural', function() { 265 | x18n.register('en', { 266 | users: { 267 | 1: 'There is 1 user online', 268 | n: 'There are %1 users online' 269 | } 270 | }); 271 | return expect(t('users')).to.have.property('plural').that.is.a('function'); 272 | }); 273 | return it('should support pluralisation', function() { 274 | x18n.register('en', { 275 | users: { 276 | 1: 'There is 1 user online', 277 | n: 'There are %1 users online' 278 | } 279 | }); 280 | expect(t('users').plural(1)).to.equal('There is 1 user online'); 281 | return expect(t('users').plural(3)).to.equal('There are 3 users online'); 282 | }); 283 | }); 284 | }); 285 | 286 | }).call(this); 287 | -------------------------------------------------------------------------------- /spec/vendor/jquery.js: -------------------------------------------------------------------------------- 1 | /*! jQuery v1.8.3 jquery.com | jquery.org/license */ 2 | (function(e,t){function _(e){var t=M[e]={};return v.each(e.split(y),function(e,n){t[n]=!0}),t}function H(e,n,r){if(r===t&&e.nodeType===1){var i="data-"+n.replace(P,"-$1").toLowerCase();r=e.getAttribute(i);if(typeof r=="string"){try{r=r==="true"?!0:r==="false"?!1:r==="null"?null:+r+""===r?+r:D.test(r)?v.parseJSON(r):r}catch(s){}v.data(e,n,r)}else r=t}return r}function B(e){var t;for(t in e){if(t==="data"&&v.isEmptyObject(e[t]))continue;if(t!=="toJSON")return!1}return!0}function et(){return!1}function tt(){return!0}function ut(e){return!e||!e.parentNode||e.parentNode.nodeType===11}function at(e,t){do e=e[t];while(e&&e.nodeType!==1);return e}function ft(e,t,n){t=t||0;if(v.isFunction(t))return v.grep(e,function(e,r){var i=!!t.call(e,r,e);return i===n});if(t.nodeType)return v.grep(e,function(e,r){return e===t===n});if(typeof t=="string"){var r=v.grep(e,function(e){return e.nodeType===1});if(it.test(t))return v.filter(t,r,!n);t=v.filter(t,r)}return v.grep(e,function(e,r){return v.inArray(e,t)>=0===n})}function lt(e){var t=ct.split("|"),n=e.createDocumentFragment();if(n.createElement)while(t.length)n.createElement(t.pop());return n}function Lt(e,t){return e.getElementsByTagName(t)[0]||e.appendChild(e.ownerDocument.createElement(t))}function At(e,t){if(t.nodeType!==1||!v.hasData(e))return;var n,r,i,s=v._data(e),o=v._data(t,s),u=s.events;if(u){delete o.handle,o.events={};for(n in u)for(r=0,i=u[n].length;r").appendTo(i.body),n=t.css("display");t.remove();if(n==="none"||n===""){Pt=i.body.appendChild(Pt||v.extend(i.createElement("iframe"),{frameBorder:0,width:0,height:0}));if(!Ht||!Pt.createElement)Ht=(Pt.contentWindow||Pt.contentDocument).document,Ht.write(""),Ht.close();t=Ht.body.appendChild(Ht.createElement(e)),n=Dt(t,"display"),i.body.removeChild(Pt)}return Wt[e]=n,n}function fn(e,t,n,r){var i;if(v.isArray(t))v.each(t,function(t,i){n||sn.test(e)?r(e,i):fn(e+"["+(typeof i=="object"?t:"")+"]",i,n,r)});else if(!n&&v.type(t)==="object")for(i in t)fn(e+"["+i+"]",t[i],n,r);else r(e,t)}function Cn(e){return function(t,n){typeof t!="string"&&(n=t,t="*");var r,i,s,o=t.toLowerCase().split(y),u=0,a=o.length;if(v.isFunction(n))for(;u)[^>]*$|#([\w\-]*)$)/,E=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,S=/^[\],:{}\s]*$/,x=/(?:^|:|,)(?:\s*\[)+/g,T=/\\(?:["\\\/bfnrt]|u[\da-fA-F]{4})/g,N=/"[^"\\\r\n]*"|true|false|null|-?(?:\d\d*\.|)\d+(?:[eE][\-+]?\d+|)/g,C=/^-ms-/,k=/-([\da-z])/gi,L=function(e,t){return(t+"").toUpperCase()},A=function(){i.addEventListener?(i.removeEventListener("DOMContentLoaded",A,!1),v.ready()):i.readyState==="complete"&&(i.detachEvent("onreadystatechange",A),v.ready())},O={};v.fn=v.prototype={constructor:v,init:function(e,n,r){var s,o,u,a;if(!e)return this;if(e.nodeType)return this.context=this[0]=e,this.length=1,this;if(typeof e=="string"){e.charAt(0)==="<"&&e.charAt(e.length-1)===">"&&e.length>=3?s=[null,e,null]:s=w.exec(e);if(s&&(s[1]||!n)){if(s[1])return n=n instanceof v?n[0]:n,a=n&&n.nodeType?n.ownerDocument||n:i,e=v.parseHTML(s[1],a,!0),E.test(s[1])&&v.isPlainObject(n)&&this.attr.call(e,n,!0),v.merge(this,e);o=i.getElementById(s[2]);if(o&&o.parentNode){if(o.id!==s[2])return r.find(e);this.length=1,this[0]=o}return this.context=i,this.selector=e,this}return!n||n.jquery?(n||r).find(e):this.constructor(n).find(e)}return v.isFunction(e)?r.ready(e):(e.selector!==t&&(this.selector=e.selector,this.context=e.context),v.makeArray(e,this))},selector:"",jquery:"1.8.3",length:0,size:function(){return this.length},toArray:function(){return l.call(this)},get:function(e){return e==null?this.toArray():e<0?this[this.length+e]:this[e]},pushStack:function(e,t,n){var r=v.merge(this.constructor(),e);return r.prevObject=this,r.context=this.context,t==="find"?r.selector=this.selector+(this.selector?" ":"")+n:t&&(r.selector=this.selector+"."+t+"("+n+")"),r},each:function(e,t){return v.each(this,e,t)},ready:function(e){return v.ready.promise().done(e),this},eq:function(e){return e=+e,e===-1?this.slice(e):this.slice(e,e+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(l.apply(this,arguments),"slice",l.call(arguments).join(","))},map:function(e){return this.pushStack(v.map(this,function(t,n){return e.call(t,n,t)}))},end:function(){return this.prevObject||this.constructor(null)},push:f,sort:[].sort,splice:[].splice},v.fn.init.prototype=v.fn,v.extend=v.fn.extend=function(){var e,n,r,i,s,o,u=arguments[0]||{},a=1,f=arguments.length,l=!1;typeof u=="boolean"&&(l=u,u=arguments[1]||{},a=2),typeof u!="object"&&!v.isFunction(u)&&(u={}),f===a&&(u=this,--a);for(;a0)return;r.resolveWith(i,[v]),v.fn.trigger&&v(i).trigger("ready").off("ready")},isFunction:function(e){return v.type(e)==="function"},isArray:Array.isArray||function(e){return v.type(e)==="array"},isWindow:function(e){return e!=null&&e==e.window},isNumeric:function(e){return!isNaN(parseFloat(e))&&isFinite(e)},type:function(e){return e==null?String(e):O[h.call(e)]||"object"},isPlainObject:function(e){if(!e||v.type(e)!=="object"||e.nodeType||v.isWindow(e))return!1;try{if(e.constructor&&!p.call(e,"constructor")&&!p.call(e.constructor.prototype,"isPrototypeOf"))return!1}catch(n){return!1}var r;for(r in e);return r===t||p.call(e,r)},isEmptyObject:function(e){var t;for(t in e)return!1;return!0},error:function(e){throw new Error(e)},parseHTML:function(e,t,n){var r;return!e||typeof e!="string"?null:(typeof t=="boolean"&&(n=t,t=0),t=t||i,(r=E.exec(e))?[t.createElement(r[1])]:(r=v.buildFragment([e],t,n?null:[]),v.merge([],(r.cacheable?v.clone(r.fragment):r.fragment).childNodes)))},parseJSON:function(t){if(!t||typeof t!="string")return null;t=v.trim(t);if(e.JSON&&e.JSON.parse)return e.JSON.parse(t);if(S.test(t.replace(T,"@").replace(N,"]").replace(x,"")))return(new Function("return "+t))();v.error("Invalid JSON: "+t)},parseXML:function(n){var r,i;if(!n||typeof n!="string")return null;try{e.DOMParser?(i=new DOMParser,r=i.parseFromString(n,"text/xml")):(r=new ActiveXObject("Microsoft.XMLDOM"),r.async="false",r.loadXML(n))}catch(s){r=t}return(!r||!r.documentElement||r.getElementsByTagName("parsererror").length)&&v.error("Invalid XML: "+n),r},noop:function(){},globalEval:function(t){t&&g.test(t)&&(e.execScript||function(t){e.eval.call(e,t)})(t)},camelCase:function(e){return e.replace(C,"ms-").replace(k,L)},nodeName:function(e,t){return e.nodeName&&e.nodeName.toLowerCase()===t.toLowerCase()},each:function(e,n,r){var i,s=0,o=e.length,u=o===t||v.isFunction(e);if(r){if(u){for(i in e)if(n.apply(e[i],r)===!1)break}else for(;s0&&e[0]&&e[a-1]||a===0||v.isArray(e));if(f)for(;u-1)a.splice(n,1),i&&(n<=o&&o--,n<=u&&u--)}),this},has:function(e){return v.inArray(e,a)>-1},empty:function(){return a=[],this},disable:function(){return a=f=n=t,this},disabled:function(){return!a},lock:function(){return f=t,n||c.disable(),this},locked:function(){return!f},fireWith:function(e,t){return t=t||[],t=[e,t.slice?t.slice():t],a&&(!r||f)&&(i?f.push(t):l(t)),this},fire:function(){return c.fireWith(this,arguments),this},fired:function(){return!!r}};return c},v.extend({Deferred:function(e){var t=[["resolve","done",v.Callbacks("once memory"),"resolved"],["reject","fail",v.Callbacks("once memory"),"rejected"],["notify","progress",v.Callbacks("memory")]],n="pending",r={state:function(){return n},always:function(){return i.done(arguments).fail(arguments),this},then:function(){var e=arguments;return v.Deferred(function(n){v.each(t,function(t,r){var s=r[0],o=e[t];i[r[1]](v.isFunction(o)?function(){var e=o.apply(this,arguments);e&&v.isFunction(e.promise)?e.promise().done(n.resolve).fail(n.reject).progress(n.notify):n[s+"With"](this===i?n:this,[e])}:n[s])}),e=null}).promise()},promise:function(e){return e!=null?v.extend(e,r):r}},i={};return r.pipe=r.then,v.each(t,function(e,s){var o=s[2],u=s[3];r[s[1]]=o.add,u&&o.add(function(){n=u},t[e^1][2].disable,t[2][2].lock),i[s[0]]=o.fire,i[s[0]+"With"]=o.fireWith}),r.promise(i),e&&e.call(i,i),i},when:function(e){var t=0,n=l.call(arguments),r=n.length,i=r!==1||e&&v.isFunction(e.promise)?r:0,s=i===1?e:v.Deferred(),o=function(e,t,n){return function(r){t[e]=this,n[e]=arguments.length>1?l.call(arguments):r,n===u?s.notifyWith(t,n):--i||s.resolveWith(t,n)}},u,a,f;if(r>1){u=new Array(r),a=new Array(r),f=new Array(r);for(;t
a",n=p.getElementsByTagName("*"),r=p.getElementsByTagName("a")[0];if(!n||!r||!n.length)return{};s=i.createElement("select"),o=s.appendChild(i.createElement("option")),u=p.getElementsByTagName("input")[0],r.style.cssText="top:1px;float:left;opacity:.5",t={leadingWhitespace:p.firstChild.nodeType===3,tbody:!p.getElementsByTagName("tbody").length,htmlSerialize:!!p.getElementsByTagName("link").length,style:/top/.test(r.getAttribute("style")),hrefNormalized:r.getAttribute("href")==="/a",opacity:/^0.5/.test(r.style.opacity),cssFloat:!!r.style.cssFloat,checkOn:u.value==="on",optSelected:o.selected,getSetAttribute:p.className!=="t",enctype:!!i.createElement("form").enctype,html5Clone:i.createElement("nav").cloneNode(!0).outerHTML!=="<:nav>",boxModel:i.compatMode==="CSS1Compat",submitBubbles:!0,changeBubbles:!0,focusinBubbles:!1,deleteExpando:!0,noCloneEvent:!0,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableMarginRight:!0,boxSizingReliable:!0,pixelPosition:!1},u.checked=!0,t.noCloneChecked=u.cloneNode(!0).checked,s.disabled=!0,t.optDisabled=!o.disabled;try{delete p.test}catch(d){t.deleteExpando=!1}!p.addEventListener&&p.attachEvent&&p.fireEvent&&(p.attachEvent("onclick",h=function(){t.noCloneEvent=!1}),p.cloneNode(!0).fireEvent("onclick"),p.detachEvent("onclick",h)),u=i.createElement("input"),u.value="t",u.setAttribute("type","radio"),t.radioValue=u.value==="t",u.setAttribute("checked","checked"),u.setAttribute("name","t"),p.appendChild(u),a=i.createDocumentFragment(),a.appendChild(p.lastChild),t.checkClone=a.cloneNode(!0).cloneNode(!0).lastChild.checked,t.appendChecked=u.checked,a.removeChild(u),a.appendChild(p);if(p.attachEvent)for(l in{submit:!0,change:!0,focusin:!0})f="on"+l,c=f in p,c||(p.setAttribute(f,"return;"),c=typeof p[f]=="function"),t[l+"Bubbles"]=c;return v(function(){var n,r,s,o,u="padding:0;margin:0;border:0;display:block;overflow:hidden;",a=i.getElementsByTagName("body")[0];if(!a)return;n=i.createElement("div"),n.style.cssText="visibility:hidden;border:0;width:0;height:0;position:static;top:0;margin-top:1px",a.insertBefore(n,a.firstChild),r=i.createElement("div"),n.appendChild(r),r.innerHTML="
t
",s=r.getElementsByTagName("td"),s[0].style.cssText="padding:0;margin:0;border:0;display:none",c=s[0].offsetHeight===0,s[0].style.display="",s[1].style.display="none",t.reliableHiddenOffsets=c&&s[0].offsetHeight===0,r.innerHTML="",r.style.cssText="box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;padding:1px;border:1px;display:block;width:4px;margin-top:1%;position:absolute;top:1%;",t.boxSizing=r.offsetWidth===4,t.doesNotIncludeMarginInBodyOffset=a.offsetTop!==1,e.getComputedStyle&&(t.pixelPosition=(e.getComputedStyle(r,null)||{}).top!=="1%",t.boxSizingReliable=(e.getComputedStyle(r,null)||{width:"4px"}).width==="4px",o=i.createElement("div"),o.style.cssText=r.style.cssText=u,o.style.marginRight=o.style.width="0",r.style.width="1px",r.appendChild(o),t.reliableMarginRight=!parseFloat((e.getComputedStyle(o,null)||{}).marginRight)),typeof r.style.zoom!="undefined"&&(r.innerHTML="",r.style.cssText=u+"width:1px;padding:1px;display:inline;zoom:1",t.inlineBlockNeedsLayout=r.offsetWidth===3,r.style.display="block",r.style.overflow="visible",r.innerHTML="
",r.firstChild.style.width="5px",t.shrinkWrapBlocks=r.offsetWidth!==3,n.style.zoom=1),a.removeChild(n),n=r=s=o=null}),a.removeChild(p),n=r=s=o=u=a=p=null,t}();var D=/(?:\{[\s\S]*\}|\[[\s\S]*\])$/,P=/([A-Z])/g;v.extend({cache:{},deletedIds:[],uuid:0,expando:"jQuery"+(v.fn.jquery+Math.random()).replace(/\D/g,""),noData:{embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:!0},hasData:function(e){return e=e.nodeType?v.cache[e[v.expando]]:e[v.expando],!!e&&!B(e)},data:function(e,n,r,i){if(!v.acceptData(e))return;var s,o,u=v.expando,a=typeof n=="string",f=e.nodeType,l=f?v.cache:e,c=f?e[u]:e[u]&&u;if((!c||!l[c]||!i&&!l[c].data)&&a&&r===t)return;c||(f?e[u]=c=v.deletedIds.pop()||v.guid++:c=u),l[c]||(l[c]={},f||(l[c].toJSON=v.noop));if(typeof n=="object"||typeof n=="function")i?l[c]=v.extend(l[c],n):l[c].data=v.extend(l[c].data,n);return s=l[c],i||(s.data||(s.data={}),s=s.data),r!==t&&(s[v.camelCase(n)]=r),a?(o=s[n],o==null&&(o=s[v.camelCase(n)])):o=s,o},removeData:function(e,t,n){if(!v.acceptData(e))return;var r,i,s,o=e.nodeType,u=o?v.cache:e,a=o?e[v.expando]:v.expando;if(!u[a])return;if(t){r=n?u[a]:u[a].data;if(r){v.isArray(t)||(t in r?t=[t]:(t=v.camelCase(t),t in r?t=[t]:t=t.split(" ")));for(i=0,s=t.length;i1,null,!1))},removeData:function(e){return this.each(function(){v.removeData(this,e)})}}),v.extend({queue:function(e,t,n){var r;if(e)return t=(t||"fx")+"queue",r=v._data(e,t),n&&(!r||v.isArray(n)?r=v._data(e,t,v.makeArray(n)):r.push(n)),r||[]},dequeue:function(e,t){t=t||"fx";var n=v.queue(e,t),r=n.length,i=n.shift(),s=v._queueHooks(e,t),o=function(){v.dequeue(e,t)};i==="inprogress"&&(i=n.shift(),r--),i&&(t==="fx"&&n.unshift("inprogress"),delete s.stop,i.call(e,o,s)),!r&&s&&s.empty.fire()},_queueHooks:function(e,t){var n=t+"queueHooks";return v._data(e,n)||v._data(e,n,{empty:v.Callbacks("once memory").add(function(){v.removeData(e,t+"queue",!0),v.removeData(e,n,!0)})})}}),v.fn.extend({queue:function(e,n){var r=2;return typeof e!="string"&&(n=e,e="fx",r--),arguments.length1)},removeAttr:function(e){return this.each(function(){v.removeAttr(this,e)})},prop:function(e,t){return v.access(this,v.prop,e,t,arguments.length>1)},removeProp:function(e){return e=v.propFix[e]||e,this.each(function(){try{this[e]=t,delete this[e]}catch(n){}})},addClass:function(e){var t,n,r,i,s,o,u;if(v.isFunction(e))return this.each(function(t){v(this).addClass(e.call(this,t,this.className))});if(e&&typeof e=="string"){t=e.split(y);for(n=0,r=this.length;n=0)r=r.replace(" "+n[s]+" "," ");i.className=e?v.trim(r):""}}}return this},toggleClass:function(e,t){var n=typeof e,r=typeof t=="boolean";return v.isFunction(e)?this.each(function(n){v(this).toggleClass(e.call(this,n,this.className,t),t)}):this.each(function(){if(n==="string"){var i,s=0,o=v(this),u=t,a=e.split(y);while(i=a[s++])u=r?u:!o.hasClass(i),o[u?"addClass":"removeClass"](i)}else if(n==="undefined"||n==="boolean")this.className&&v._data(this,"__className__",this.className),this.className=this.className||e===!1?"":v._data(this,"__className__")||""})},hasClass:function(e){var t=" "+e+" ",n=0,r=this.length;for(;n=0)return!0;return!1},val:function(e){var n,r,i,s=this[0];if(!arguments.length){if(s)return n=v.valHooks[s.type]||v.valHooks[s.nodeName.toLowerCase()],n&&"get"in n&&(r=n.get(s,"value"))!==t?r:(r=s.value,typeof r=="string"?r.replace(R,""):r==null?"":r);return}return i=v.isFunction(e),this.each(function(r){var s,o=v(this);if(this.nodeType!==1)return;i?s=e.call(this,r,o.val()):s=e,s==null?s="":typeof s=="number"?s+="":v.isArray(s)&&(s=v.map(s,function(e){return e==null?"":e+""})),n=v.valHooks[this.type]||v.valHooks[this.nodeName.toLowerCase()];if(!n||!("set"in n)||n.set(this,s,"value")===t)this.value=s})}}),v.extend({valHooks:{option:{get:function(e){var t=e.attributes.value;return!t||t.specified?e.value:e.text}},select:{get:function(e){var t,n,r=e.options,i=e.selectedIndex,s=e.type==="select-one"||i<0,o=s?null:[],u=s?i+1:r.length,a=i<0?u:s?i:0;for(;a=0}),n.length||(e.selectedIndex=-1),n}}},attrFn:{},attr:function(e,n,r,i){var s,o,u,a=e.nodeType;if(!e||a===3||a===8||a===2)return;if(i&&v.isFunction(v.fn[n]))return v(e)[n](r);if(typeof e.getAttribute=="undefined")return v.prop(e,n,r);u=a!==1||!v.isXMLDoc(e),u&&(n=n.toLowerCase(),o=v.attrHooks[n]||(X.test(n)?F:j));if(r!==t){if(r===null){v.removeAttr(e,n);return}return o&&"set"in o&&u&&(s=o.set(e,r,n))!==t?s:(e.setAttribute(n,r+""),r)}return o&&"get"in o&&u&&(s=o.get(e,n))!==null?s:(s=e.getAttribute(n),s===null?t:s)},removeAttr:function(e,t){var n,r,i,s,o=0;if(t&&e.nodeType===1){r=t.split(y);for(;o=0}})});var $=/^(?:textarea|input|select)$/i,J=/^([^\.]*|)(?:\.(.+)|)$/,K=/(?:^|\s)hover(\.\S+|)\b/,Q=/^key/,G=/^(?:mouse|contextmenu)|click/,Y=/^(?:focusinfocus|focusoutblur)$/,Z=function(e){return v.event.special.hover?e:e.replace(K,"mouseenter$1 mouseleave$1")};v.event={add:function(e,n,r,i,s){var o,u,a,f,l,c,h,p,d,m,g;if(e.nodeType===3||e.nodeType===8||!n||!r||!(o=v._data(e)))return;r.handler&&(d=r,r=d.handler,s=d.selector),r.guid||(r.guid=v.guid++),a=o.events,a||(o.events=a={}),u=o.handle,u||(o.handle=u=function(e){return typeof v=="undefined"||!!e&&v.event.triggered===e.type?t:v.event.dispatch.apply(u.elem,arguments)},u.elem=e),n=v.trim(Z(n)).split(" ");for(f=0;f=0&&(y=y.slice(0,-1),a=!0),y.indexOf(".")>=0&&(b=y.split("."),y=b.shift(),b.sort());if((!s||v.event.customEvent[y])&&!v.event.global[y])return;n=typeof n=="object"?n[v.expando]?n:new v.Event(y,n):new v.Event(y),n.type=y,n.isTrigger=!0,n.exclusive=a,n.namespace=b.join("."),n.namespace_re=n.namespace?new RegExp("(^|\\.)"+b.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,h=y.indexOf(":")<0?"on"+y:"";if(!s){u=v.cache;for(f in u)u[f].events&&u[f].events[y]&&v.event.trigger(n,r,u[f].handle.elem,!0);return}n.result=t,n.target||(n.target=s),r=r!=null?v.makeArray(r):[],r.unshift(n),p=v.event.special[y]||{};if(p.trigger&&p.trigger.apply(s,r)===!1)return;m=[[s,p.bindType||y]];if(!o&&!p.noBubble&&!v.isWindow(s)){g=p.delegateType||y,l=Y.test(g+y)?s:s.parentNode;for(c=s;l;l=l.parentNode)m.push([l,g]),c=l;c===(s.ownerDocument||i)&&m.push([c.defaultView||c.parentWindow||e,g])}for(f=0;f=0:v.find(h,this,null,[s]).length),u[h]&&f.push(c);f.length&&w.push({elem:s,matches:f})}d.length>m&&w.push({elem:this,matches:d.slice(m)});for(r=0;r0?this.on(t,null,e,n):this.trigger(t)},Q.test(t)&&(v.event.fixHooks[t]=v.event.keyHooks),G.test(t)&&(v.event.fixHooks[t]=v.event.mouseHooks)}),function(e,t){function nt(e,t,n,r){n=n||[],t=t||g;var i,s,a,f,l=t.nodeType;if(!e||typeof e!="string")return n;if(l!==1&&l!==9)return[];a=o(t);if(!a&&!r)if(i=R.exec(e))if(f=i[1]){if(l===9){s=t.getElementById(f);if(!s||!s.parentNode)return n;if(s.id===f)return n.push(s),n}else if(t.ownerDocument&&(s=t.ownerDocument.getElementById(f))&&u(t,s)&&s.id===f)return n.push(s),n}else{if(i[2])return S.apply(n,x.call(t.getElementsByTagName(e),0)),n;if((f=i[3])&&Z&&t.getElementsByClassName)return S.apply(n,x.call(t.getElementsByClassName(f),0)),n}return vt(e.replace(j,"$1"),t,n,r,a)}function rt(e){return function(t){var n=t.nodeName.toLowerCase();return n==="input"&&t.type===e}}function it(e){return function(t){var n=t.nodeName.toLowerCase();return(n==="input"||n==="button")&&t.type===e}}function st(e){return N(function(t){return t=+t,N(function(n,r){var i,s=e([],n.length,t),o=s.length;while(o--)n[i=s[o]]&&(n[i]=!(r[i]=n[i]))})})}function ot(e,t,n){if(e===t)return n;var r=e.nextSibling;while(r){if(r===t)return-1;r=r.nextSibling}return 1}function ut(e,t){var n,r,s,o,u,a,f,l=L[d][e+" "];if(l)return t?0:l.slice(0);u=e,a=[],f=i.preFilter;while(u){if(!n||(r=F.exec(u)))r&&(u=u.slice(r[0].length)||u),a.push(s=[]);n=!1;if(r=I.exec(u))s.push(n=new m(r.shift())),u=u.slice(n.length),n.type=r[0].replace(j," ");for(o in i.filter)(r=J[o].exec(u))&&(!f[o]||(r=f[o](r)))&&(s.push(n=new m(r.shift())),u=u.slice(n.length),n.type=o,n.matches=r);if(!n)break}return t?u.length:u?nt.error(e):L(e,a).slice(0)}function at(e,t,r){var i=t.dir,s=r&&t.dir==="parentNode",o=w++;return t.first?function(t,n,r){while(t=t[i])if(s||t.nodeType===1)return e(t,n,r)}:function(t,r,u){if(!u){var a,f=b+" "+o+" ",l=f+n;while(t=t[i])if(s||t.nodeType===1){if((a=t[d])===l)return t.sizset;if(typeof a=="string"&&a.indexOf(f)===0){if(t.sizset)return t}else{t[d]=l;if(e(t,r,u))return t.sizset=!0,t;t.sizset=!1}}}else while(t=t[i])if(s||t.nodeType===1)if(e(t,r,u))return t}}function ft(e){return e.length>1?function(t,n,r){var i=e.length;while(i--)if(!e[i](t,n,r))return!1;return!0}:e[0]}function lt(e,t,n,r,i){var s,o=[],u=0,a=e.length,f=t!=null;for(;u-1&&(s[f]=!(o[f]=c))}}else g=lt(g===o?g.splice(d,g.length):g),i?i(null,o,g,a):S.apply(o,g)})}function ht(e){var t,n,r,s=e.length,o=i.relative[e[0].type],u=o||i.relative[" "],a=o?1:0,f=at(function(e){return e===t},u,!0),l=at(function(e){return T.call(t,e)>-1},u,!0),h=[function(e,n,r){return!o&&(r||n!==c)||((t=n).nodeType?f(e,n,r):l(e,n,r))}];for(;a1&&ft(h),a>1&&e.slice(0,a-1).join("").replace(j,"$1"),n,a0,s=e.length>0,o=function(u,a,f,l,h){var p,d,v,m=[],y=0,w="0",x=u&&[],T=h!=null,N=c,C=u||s&&i.find.TAG("*",h&&a.parentNode||a),k=b+=N==null?1:Math.E;T&&(c=a!==g&&a,n=o.el);for(;(p=C[w])!=null;w++){if(s&&p){for(d=0;v=e[d];d++)if(v(p,a,f)){l.push(p);break}T&&(b=k,n=++o.el)}r&&((p=!v&&p)&&y--,u&&x.push(p))}y+=w;if(r&&w!==y){for(d=0;v=t[d];d++)v(x,m,a,f);if(u){if(y>0)while(w--)!x[w]&&!m[w]&&(m[w]=E.call(l));m=lt(m)}S.apply(l,m),T&&!u&&m.length>0&&y+t.length>1&&nt.uniqueSort(l)}return T&&(b=k,c=N),x};return o.el=0,r?N(o):o}function dt(e,t,n){var r=0,i=t.length;for(;r2&&(f=u[0]).type==="ID"&&t.nodeType===9&&!s&&i.relative[u[1].type]){t=i.find.ID(f.matches[0].replace($,""),t,s)[0];if(!t)return n;e=e.slice(u.shift().length)}for(o=J.POS.test(e)?-1:u.length-1;o>=0;o--){f=u[o];if(i.relative[l=f.type])break;if(c=i.find[l])if(r=c(f.matches[0].replace($,""),z.test(u[0].type)&&t.parentNode||t,s)){u.splice(o,1),e=r.length&&u.join("");if(!e)return S.apply(n,x.call(r,0)),n;break}}}return a(e,h)(r,t,s,n,z.test(e)),n}function mt(){}var n,r,i,s,o,u,a,f,l,c,h=!0,p="undefined",d=("sizcache"+Math.random()).replace(".",""),m=String,g=e.document,y=g.documentElement,b=0,w=0,E=[].pop,S=[].push,x=[].slice,T=[].indexOf||function(e){var t=0,n=this.length;for(;ti.cacheLength&&delete e[t.shift()],e[n+" "]=r},e)},k=C(),L=C(),A=C(),O="[\\x20\\t\\r\\n\\f]",M="(?:\\\\.|[-\\w]|[^\\x00-\\xa0])+",_=M.replace("w","w#"),D="([*^$|!~]?=)",P="\\["+O+"*("+M+")"+O+"*(?:"+D+O+"*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|("+_+")|)|)"+O+"*\\]",H=":("+M+")(?:\\((?:(['\"])((?:\\\\.|[^\\\\])*?)\\2|([^()[\\]]*|(?:(?:"+P+")|[^:]|\\\\.)*|.*))\\)|)",B=":(even|odd|eq|gt|lt|nth|first|last)(?:\\("+O+"*((?:-\\d)?\\d*)"+O+"*\\)|)(?=[^-]|$)",j=new RegExp("^"+O+"+|((?:^|[^\\\\])(?:\\\\.)*)"+O+"+$","g"),F=new RegExp("^"+O+"*,"+O+"*"),I=new RegExp("^"+O+"*([\\x20\\t\\r\\n\\f>+~])"+O+"*"),q=new RegExp(H),R=/^(?:#([\w\-]+)|(\w+)|\.([\w\-]+))$/,U=/^:not/,z=/[\x20\t\r\n\f]*[+~]/,W=/:not\($/,X=/h\d/i,V=/input|select|textarea|button/i,$=/\\(?!\\)/g,J={ID:new RegExp("^#("+M+")"),CLASS:new RegExp("^\\.("+M+")"),NAME:new RegExp("^\\[name=['\"]?("+M+")['\"]?\\]"),TAG:new RegExp("^("+M.replace("w","w*")+")"),ATTR:new RegExp("^"+P),PSEUDO:new RegExp("^"+H),POS:new RegExp(B,"i"),CHILD:new RegExp("^:(only|nth|first|last)-child(?:\\("+O+"*(even|odd|(([+-]|)(\\d*)n|)"+O+"*(?:([+-]|)"+O+"*(\\d+)|))"+O+"*\\)|)","i"),needsContext:new RegExp("^"+O+"*[>+~]|"+B,"i")},K=function(e){var t=g.createElement("div");try{return e(t)}catch(n){return!1}finally{t=null}},Q=K(function(e){return e.appendChild(g.createComment("")),!e.getElementsByTagName("*").length}),G=K(function(e){return e.innerHTML="",e.firstChild&&typeof e.firstChild.getAttribute!==p&&e.firstChild.getAttribute("href")==="#"}),Y=K(function(e){e.innerHTML="";var t=typeof e.lastChild.getAttribute("multiple");return t!=="boolean"&&t!=="string"}),Z=K(function(e){return e.innerHTML="",!e.getElementsByClassName||!e.getElementsByClassName("e").length?!1:(e.lastChild.className="e",e.getElementsByClassName("e").length===2)}),et=K(function(e){e.id=d+0,e.innerHTML="
",y.insertBefore(e,y.firstChild);var t=g.getElementsByName&&g.getElementsByName(d).length===2+g.getElementsByName(d+0).length;return r=!g.getElementById(d),y.removeChild(e),t});try{x.call(y.childNodes,0)[0].nodeType}catch(tt){x=function(e){var t,n=[];for(;t=this[e];e++)n.push(t);return n}}nt.matches=function(e,t){return nt(e,null,null,t)},nt.matchesSelector=function(e,t){return nt(t,null,null,[e]).length>0},s=nt.getText=function(e){var t,n="",r=0,i=e.nodeType;if(i){if(i===1||i===9||i===11){if(typeof e.textContent=="string")return e.textContent;for(e=e.firstChild;e;e=e.nextSibling)n+=s(e)}else if(i===3||i===4)return e.nodeValue}else for(;t=e[r];r++)n+=s(t);return n},o=nt.isXML=function(e){var t=e&&(e.ownerDocument||e).documentElement;return t?t.nodeName!=="HTML":!1},u=nt.contains=y.contains?function(e,t){var n=e.nodeType===9?e.documentElement:e,r=t&&t.parentNode;return e===r||!!(r&&r.nodeType===1&&n.contains&&n.contains(r))}:y.compareDocumentPosition?function(e,t){return t&&!!(e.compareDocumentPosition(t)&16)}:function(e,t){while(t=t.parentNode)if(t===e)return!0;return!1},nt.attr=function(e,t){var n,r=o(e);return r||(t=t.toLowerCase()),(n=i.attrHandle[t])?n(e):r||Y?e.getAttribute(t):(n=e.getAttributeNode(t),n?typeof e[t]=="boolean"?e[t]?t:null:n.specified?n.value:null:null)},i=nt.selectors={cacheLength:50,createPseudo:N,match:J,attrHandle:G?{}:{href:function(e){return e.getAttribute("href",2)},type:function(e){return e.getAttribute("type")}},find:{ID:r?function(e,t,n){if(typeof t.getElementById!==p&&!n){var r=t.getElementById(e);return r&&r.parentNode?[r]:[]}}:function(e,n,r){if(typeof n.getElementById!==p&&!r){var i=n.getElementById(e);return i?i.id===e||typeof i.getAttributeNode!==p&&i.getAttributeNode("id").value===e?[i]:t:[]}},TAG:Q?function(e,t){if(typeof t.getElementsByTagName!==p)return t.getElementsByTagName(e)}:function(e,t){var n=t.getElementsByTagName(e);if(e==="*"){var r,i=[],s=0;for(;r=n[s];s++)r.nodeType===1&&i.push(r);return i}return n},NAME:et&&function(e,t){if(typeof t.getElementsByName!==p)return t.getElementsByName(name)},CLASS:Z&&function(e,t,n){if(typeof t.getElementsByClassName!==p&&!n)return t.getElementsByClassName(e)}},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace($,""),e[3]=(e[4]||e[5]||"").replace($,""),e[2]==="~="&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),e[1]==="nth"?(e[2]||nt.error(e[0]),e[3]=+(e[3]?e[4]+(e[5]||1):2*(e[2]==="even"||e[2]==="odd")),e[4]=+(e[6]+e[7]||e[2]==="odd")):e[2]&&nt.error(e[0]),e},PSEUDO:function(e){var t,n;if(J.CHILD.test(e[0]))return null;if(e[3])e[2]=e[3];else if(t=e[4])q.test(t)&&(n=ut(t,!0))&&(n=t.indexOf(")",t.length-n)-t.length)&&(t=t.slice(0,n),e[0]=e[0].slice(0,n)),e[2]=t;return e.slice(0,3)}},filter:{ID:r?function(e){return e=e.replace($,""),function(t){return t.getAttribute("id")===e}}:function(e){return e=e.replace($,""),function(t){var n=typeof t.getAttributeNode!==p&&t.getAttributeNode("id");return n&&n.value===e}},TAG:function(e){return e==="*"?function(){return!0}:(e=e.replace($,"").toLowerCase(),function(t){return t.nodeName&&t.nodeName.toLowerCase()===e})},CLASS:function(e){var t=k[d][e+" "];return t||(t=new RegExp("(^|"+O+")"+e+"("+O+"|$)"))&&k(e,function(e){return t.test(e.className||typeof e.getAttribute!==p&&e.getAttribute("class")||"")})},ATTR:function(e,t,n){return function(r,i){var s=nt.attr(r,e);return s==null?t==="!=":t?(s+="",t==="="?s===n:t==="!="?s!==n:t==="^="?n&&s.indexOf(n)===0:t==="*="?n&&s.indexOf(n)>-1:t==="$="?n&&s.substr(s.length-n.length)===n:t==="~="?(" "+s+" ").indexOf(n)>-1:t==="|="?s===n||s.substr(0,n.length+1)===n+"-":!1):!0}},CHILD:function(e,t,n,r){return e==="nth"?function(e){var t,i,s=e.parentNode;if(n===1&&r===0)return!0;if(s){i=0;for(t=s.firstChild;t;t=t.nextSibling)if(t.nodeType===1){i++;if(e===t)break}}return i-=r,i===n||i%n===0&&i/n>=0}:function(t){var n=t;switch(e){case"only":case"first":while(n=n.previousSibling)if(n.nodeType===1)return!1;if(e==="first")return!0;n=t;case"last":while(n=n.nextSibling)if(n.nodeType===1)return!1;return!0}}},PSEUDO:function(e,t){var n,r=i.pseudos[e]||i.setFilters[e.toLowerCase()]||nt.error("unsupported pseudo: "+e);return r[d]?r(t):r.length>1?(n=[e,e,"",t],i.setFilters.hasOwnProperty(e.toLowerCase())?N(function(e,n){var i,s=r(e,t),o=s.length;while(o--)i=T.call(e,s[o]),e[i]=!(n[i]=s[o])}):function(e){return r(e,0,n)}):r}},pseudos:{not:N(function(e){var t=[],n=[],r=a(e.replace(j,"$1"));return r[d]?N(function(e,t,n,i){var s,o=r(e,null,i,[]),u=e.length;while(u--)if(s=o[u])e[u]=!(t[u]=s)}):function(e,i,s){return t[0]=e,r(t,null,s,n),!n.pop()}}),has:N(function(e){return function(t){return nt(e,t).length>0}}),contains:N(function(e){return function(t){return(t.textContent||t.innerText||s(t)).indexOf(e)>-1}}),enabled:function(e){return e.disabled===!1},disabled:function(e){return e.disabled===!0},checked:function(e){var t=e.nodeName.toLowerCase();return t==="input"&&!!e.checked||t==="option"&&!!e.selected},selected:function(e){return e.parentNode&&e.parentNode.selectedIndex,e.selected===!0},parent:function(e){return!i.pseudos.empty(e)},empty:function(e){var t;e=e.firstChild;while(e){if(e.nodeName>"@"||(t=e.nodeType)===3||t===4)return!1;e=e.nextSibling}return!0},header:function(e){return X.test(e.nodeName)},text:function(e){var t,n;return e.nodeName.toLowerCase()==="input"&&(t=e.type)==="text"&&((n=e.getAttribute("type"))==null||n.toLowerCase()===t)},radio:rt("radio"),checkbox:rt("checkbox"),file:rt("file"),password:rt("password"),image:rt("image"),submit:it("submit"),reset:it("reset"),button:function(e){var t=e.nodeName.toLowerCase();return t==="input"&&e.type==="button"||t==="button"},input:function(e){return V.test(e.nodeName)},focus:function(e){var t=e.ownerDocument;return e===t.activeElement&&(!t.hasFocus||t.hasFocus())&&!!(e.type||e.href||~e.tabIndex)},active:function(e){return e===e.ownerDocument.activeElement},first:st(function(){return[0]}),last:st(function(e,t){return[t-1]}),eq:st(function(e,t,n){return[n<0?n+t:n]}),even:st(function(e,t){for(var n=0;n=0;)e.push(r);return e}),gt:st(function(e,t,n){for(var r=n<0?n+t:n;++r",e.querySelectorAll("[selected]").length||i.push("\\["+O+"*(?:checked|disabled|ismap|multiple|readonly|selected|value)"),e.querySelectorAll(":checked").length||i.push(":checked")}),K(function(e){e.innerHTML="

",e.querySelectorAll("[test^='']").length&&i.push("[*^$]="+O+"*(?:\"\"|'')"),e.innerHTML="",e.querySelectorAll(":enabled").length||i.push(":enabled",":disabled")}),i=new RegExp(i.join("|")),vt=function(e,r,s,o,u){if(!o&&!u&&!i.test(e)){var a,f,l=!0,c=d,h=r,p=r.nodeType===9&&e;if(r.nodeType===1&&r.nodeName.toLowerCase()!=="object"){a=ut(e),(l=r.getAttribute("id"))?c=l.replace(n,"\\$&"):r.setAttribute("id",c),c="[id='"+c+"'] ",f=a.length;while(f--)a[f]=c+a[f].join("");h=z.test(e)&&r.parentNode||r,p=a.join(",")}if(p)try{return S.apply(s,x.call(h.querySelectorAll(p),0)),s}catch(v){}finally{l||r.removeAttribute("id")}}return t(e,r,s,o,u)},u&&(K(function(t){e=u.call(t,"div");try{u.call(t,"[test!='']:sizzle"),s.push("!=",H)}catch(n){}}),s=new RegExp(s.join("|")),nt.matchesSelector=function(t,n){n=n.replace(r,"='$1']");if(!o(t)&&!s.test(n)&&!i.test(n))try{var a=u.call(t,n);if(a||e||t.document&&t.document.nodeType!==11)return a}catch(f){}return nt(n,null,null,[t]).length>0})}(),i.pseudos.nth=i.pseudos.eq,i.filters=mt.prototype=i.pseudos,i.setFilters=new mt,nt.attr=v.attr,v.find=nt,v.expr=nt.selectors,v.expr[":"]=v.expr.pseudos,v.unique=nt.uniqueSort,v.text=nt.getText,v.isXMLDoc=nt.isXML,v.contains=nt.contains}(e);var nt=/Until$/,rt=/^(?:parents|prev(?:Until|All))/,it=/^.[^:#\[\.,]*$/,st=v.expr.match.needsContext,ot={children:!0,contents:!0,next:!0,prev:!0};v.fn.extend({find:function(e){var t,n,r,i,s,o,u=this;if(typeof e!="string")return v(e).filter(function(){for(t=0,n=u.length;t0)for(i=r;i=0:v.filter(e,this).length>0:this.filter(e).length>0)},closest:function(e,t){var n,r=0,i=this.length,s=[],o=st.test(e)||typeof e!="string"?v(e,t||this.context):0;for(;r-1:v.find.matchesSelector(n,e)){s.push(n);break}n=n.parentNode}}return s=s.length>1?v.unique(s):s,this.pushStack(s,"closest",e)},index:function(e){return e?typeof e=="string"?v.inArray(this[0],v(e)):v.inArray(e.jquery?e[0]:e,this):this[0]&&this[0].parentNode?this.prevAll().length:-1},add:function(e,t){var n=typeof e=="string"?v(e,t):v.makeArray(e&&e.nodeType?[e]:e),r=v.merge(this.get(),n);return this.pushStack(ut(n[0])||ut(r[0])?r:v.unique(r))},addBack:function(e){return this.add(e==null?this.prevObject:this.prevObject.filter(e))}}),v.fn.andSelf=v.fn.addBack,v.each({parent:function(e){var t=e.parentNode;return t&&t.nodeType!==11?t:null},parents:function(e){return v.dir(e,"parentNode")},parentsUntil:function(e,t,n){return v.dir(e,"parentNode",n)},next:function(e){return at(e,"nextSibling")},prev:function(e){return at(e,"previousSibling")},nextAll:function(e){return v.dir(e,"nextSibling")},prevAll:function(e){return v.dir(e,"previousSibling")},nextUntil:function(e,t,n){return v.dir(e,"nextSibling",n)},prevUntil:function(e,t,n){return v.dir(e,"previousSibling",n)},siblings:function(e){return v.sibling((e.parentNode||{}).firstChild,e)},children:function(e){return v.sibling(e.firstChild)},contents:function(e){return v.nodeName(e,"iframe")?e.contentDocument||e.contentWindow.document:v.merge([],e.childNodes)}},function(e,t){v.fn[e]=function(n,r){var i=v.map(this,t,n);return nt.test(e)||(r=n),r&&typeof r=="string"&&(i=v.filter(r,i)),i=this.length>1&&!ot[e]?v.unique(i):i,this.length>1&&rt.test(e)&&(i=i.reverse()),this.pushStack(i,e,l.call(arguments).join(","))}}),v.extend({filter:function(e,t,n){return n&&(e=":not("+e+")"),t.length===1?v.find.matchesSelector(t[0],e)?[t[0]]:[]:v.find.matches(e,t)},dir:function(e,n,r){var i=[],s=e[n];while(s&&s.nodeType!==9&&(r===t||s.nodeType!==1||!v(s).is(r)))s.nodeType===1&&i.push(s),s=s[n];return i},sibling:function(e,t){var n=[];for(;e;e=e.nextSibling)e.nodeType===1&&e!==t&&n.push(e);return n}});var ct="abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",ht=/ jQuery\d+="(?:null|\d+)"/g,pt=/^\s+/,dt=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,vt=/<([\w:]+)/,mt=/]","i"),Et=/^(?:checkbox|radio)$/,St=/checked\s*(?:[^=]|=\s*.checked.)/i,xt=/\/(java|ecma)script/i,Tt=/^\s*\s*$/g,Nt={option:[1,""],legend:[1,"
","
"],thead:[1,"","
"],tr:[2,"","
"],td:[3,"","
"],col:[2,"","
"],area:[1,"",""],_default:[0,"",""]},Ct=lt(i),kt=Ct.appendChild(i.createElement("div"));Nt.optgroup=Nt.option,Nt.tbody=Nt.tfoot=Nt.colgroup=Nt.caption=Nt.thead,Nt.th=Nt.td,v.support.htmlSerialize||(Nt._default=[1,"X
","
"]),v.fn.extend({text:function(e){return v.access(this,function(e){return e===t?v.text(this):this.empty().append((this[0]&&this[0].ownerDocument||i).createTextNode(e))},null,e,arguments.length)},wrapAll:function(e){if(v.isFunction(e))return this.each(function(t){v(this).wrapAll(e.call(this,t))});if(this[0]){var t=v(e,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&t.insertBefore(this[0]),t.map(function(){var e=this;while(e.firstChild&&e.firstChild.nodeType===1)e=e.firstChild;return e}).append(this)}return this},wrapInner:function(e){return v.isFunction(e)?this.each(function(t){v(this).wrapInner(e.call(this,t))}):this.each(function(){var t=v(this),n=t.contents();n.length?n.wrapAll(e):t.append(e)})},wrap:function(e){var t=v.isFunction(e);return this.each(function(n){v(this).wrapAll(t?e.call(this,n):e)})},unwrap:function(){return this.parent().each(function(){v.nodeName(this,"body")||v(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,!0,function(e){(this.nodeType===1||this.nodeType===11)&&this.appendChild(e)})},prepend:function(){return this.domManip(arguments,!0,function(e){(this.nodeType===1||this.nodeType===11)&&this.insertBefore(e,this.firstChild)})},before:function(){if(!ut(this[0]))return this.domManip(arguments,!1,function(e){this.parentNode.insertBefore(e,this)});if(arguments.length){var e=v.clean(arguments);return this.pushStack(v.merge(e,this),"before",this.selector)}},after:function(){if(!ut(this[0]))return this.domManip(arguments,!1,function(e){this.parentNode.insertBefore(e,this.nextSibling)});if(arguments.length){var e=v.clean(arguments);return this.pushStack(v.merge(this,e),"after",this.selector)}},remove:function(e,t){var n,r=0;for(;(n=this[r])!=null;r++)if(!e||v.filter(e,[n]).length)!t&&n.nodeType===1&&(v.cleanData(n.getElementsByTagName("*")),v.cleanData([n])),n.parentNode&&n.parentNode.removeChild(n);return this},empty:function(){var e,t=0;for(;(e=this[t])!=null;t++){e.nodeType===1&&v.cleanData(e.getElementsByTagName("*"));while(e.firstChild)e.removeChild(e.firstChild)}return this},clone:function(e,t){return e=e==null?!1:e,t=t==null?e:t,this.map(function(){return v.clone(this,e,t)})},html:function(e){return v.access(this,function(e){var n=this[0]||{},r=0,i=this.length;if(e===t)return n.nodeType===1?n.innerHTML.replace(ht,""):t;if(typeof e=="string"&&!yt.test(e)&&(v.support.htmlSerialize||!wt.test(e))&&(v.support.leadingWhitespace||!pt.test(e))&&!Nt[(vt.exec(e)||["",""])[1].toLowerCase()]){e=e.replace(dt,"<$1>");try{for(;r1&&typeof f=="string"&&St.test(f))return this.each(function(){v(this).domManip(e,n,r)});if(v.isFunction(f))return this.each(function(i){var s=v(this);e[0]=f.call(this,i,n?s.html():t),s.domManip(e,n,r)});if(this[0]){i=v.buildFragment(e,this,l),o=i.fragment,s=o.firstChild,o.childNodes.length===1&&(o=s);if(s){n=n&&v.nodeName(s,"tr");for(u=i.cacheable||c-1;a0?this.clone(!0):this).get(),v(o[i])[t](r),s=s.concat(r);return this.pushStack(s,e,o.selector)}}),v.extend({clone:function(e,t,n){var r,i,s,o;v.support.html5Clone||v.isXMLDoc(e)||!wt.test("<"+e.nodeName+">")?o=e.cloneNode(!0):(kt.innerHTML=e.outerHTML,kt.removeChild(o=kt.firstChild));if((!v.support.noCloneEvent||!v.support.noCloneChecked)&&(e.nodeType===1||e.nodeType===11)&&!v.isXMLDoc(e)){Ot(e,o),r=Mt(e),i=Mt(o);for(s=0;r[s];++s)i[s]&&Ot(r[s],i[s])}if(t){At(e,o);if(n){r=Mt(e),i=Mt(o);for(s=0;r[s];++s)At(r[s],i[s])}}return r=i=null,o},clean:function(e,t,n,r){var s,o,u,a,f,l,c,h,p,d,m,g,y=t===i&&Ct,b=[];if(!t||typeof t.createDocumentFragment=="undefined")t=i;for(s=0;(u=e[s])!=null;s++){typeof u=="number"&&(u+="");if(!u)continue;if(typeof u=="string")if(!gt.test(u))u=t.createTextNode(u);else{y=y||lt(t),c=t.createElement("div"),y.appendChild(c),u=u.replace(dt,"<$1>"),a=(vt.exec(u)||["",""])[1].toLowerCase(),f=Nt[a]||Nt._default,l=f[0],c.innerHTML=f[1]+u+f[2];while(l--)c=c.lastChild;if(!v.support.tbody){h=mt.test(u),p=a==="table"&&!h?c.firstChild&&c.firstChild.childNodes:f[1]===""&&!h?c.childNodes:[];for(o=p.length-1;o>=0;--o)v.nodeName(p[o],"tbody")&&!p[o].childNodes.length&&p[o].parentNode.removeChild(p[o])}!v.support.leadingWhitespace&&pt.test(u)&&c.insertBefore(t.createTextNode(pt.exec(u)[0]),c.firstChild),u=c.childNodes,c.parentNode.removeChild(c)}u.nodeType?b.push(u):v.merge(b,u)}c&&(u=c=y=null);if(!v.support.appendChecked)for(s=0;(u=b[s])!=null;s++)v.nodeName(u,"input")?_t(u):typeof u.getElementsByTagName!="undefined"&&v.grep(u.getElementsByTagName("input"),_t);if(n){m=function(e){if(!e.type||xt.test(e.type))return r?r.push(e.parentNode?e.parentNode.removeChild(e):e):n.appendChild(e)};for(s=0;(u=b[s])!=null;s++)if(!v.nodeName(u,"script")||!m(u))n.appendChild(u),typeof u.getElementsByTagName!="undefined"&&(g=v.grep(v.merge([],u.getElementsByTagName("script")),m),b.splice.apply(b,[s+1,0].concat(g)),s+=g.length)}return b},cleanData:function(e,t){var n,r,i,s,o=0,u=v.expando,a=v.cache,f=v.support.deleteExpando,l=v.event.special;for(;(i=e[o])!=null;o++)if(t||v.acceptData(i)){r=i[u],n=r&&a[r];if(n){if(n.events)for(s in n.events)l[s]?v.event.remove(i,s):v.removeEvent(i,s,n.handle);a[r]&&(delete a[r],f?delete i[u]:i.removeAttribute?i.removeAttribute(u):i[u]=null,v.deletedIds.push(r))}}}}),function(){var e,t;v.uaMatch=function(e){e=e.toLowerCase();var t=/(chrome)[ \/]([\w.]+)/.exec(e)||/(webkit)[ \/]([\w.]+)/.exec(e)||/(opera)(?:.*version|)[ \/]([\w.]+)/.exec(e)||/(msie) ([\w.]+)/.exec(e)||e.indexOf("compatible")<0&&/(mozilla)(?:.*? rv:([\w.]+)|)/.exec(e)||[];return{browser:t[1]||"",version:t[2]||"0"}},e=v.uaMatch(o.userAgent),t={},e.browser&&(t[e.browser]=!0,t.version=e.version),t.chrome?t.webkit=!0:t.webkit&&(t.safari=!0),v.browser=t,v.sub=function(){function e(t,n){return new e.fn.init(t,n)}v.extend(!0,e,this),e.superclass=this,e.fn=e.prototype=this(),e.fn.constructor=e,e.sub=this.sub,e.fn.init=function(r,i){return i&&i instanceof v&&!(i instanceof e)&&(i=e(i)),v.fn.init.call(this,r,i,t)},e.fn.init.prototype=e.fn;var t=e(i);return e}}();var Dt,Pt,Ht,Bt=/alpha\([^)]*\)/i,jt=/opacity=([^)]*)/,Ft=/^(top|right|bottom|left)$/,It=/^(none|table(?!-c[ea]).+)/,qt=/^margin/,Rt=new RegExp("^("+m+")(.*)$","i"),Ut=new RegExp("^("+m+")(?!px)[a-z%]+$","i"),zt=new RegExp("^([-+])=("+m+")","i"),Wt={BODY:"block"},Xt={position:"absolute",visibility:"hidden",display:"block"},Vt={letterSpacing:0,fontWeight:400},$t=["Top","Right","Bottom","Left"],Jt=["Webkit","O","Moz","ms"],Kt=v.fn.toggle;v.fn.extend({css:function(e,n){return v.access(this,function(e,n,r){return r!==t?v.style(e,n,r):v.css(e,n)},e,n,arguments.length>1)},show:function(){return Yt(this,!0)},hide:function(){return Yt(this)},toggle:function(e,t){var n=typeof e=="boolean";return v.isFunction(e)&&v.isFunction(t)?Kt.apply(this,arguments):this.each(function(){(n?e:Gt(this))?v(this).show():v(this).hide()})}}),v.extend({cssHooks:{opacity:{get:function(e,t){if(t){var n=Dt(e,"opacity");return n===""?"1":n}}}},cssNumber:{fillOpacity:!0,fontWeight:!0,lineHeight:!0,opacity:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":v.support.cssFloat?"cssFloat":"styleFloat"},style:function(e,n,r,i){if(!e||e.nodeType===3||e.nodeType===8||!e.style)return;var s,o,u,a=v.camelCase(n),f=e.style;n=v.cssProps[a]||(v.cssProps[a]=Qt(f,a)),u=v.cssHooks[n]||v.cssHooks[a];if(r===t)return u&&"get"in u&&(s=u.get(e,!1,i))!==t?s:f[n];o=typeof r,o==="string"&&(s=zt.exec(r))&&(r=(s[1]+1)*s[2]+parseFloat(v.css(e,n)),o="number");if(r==null||o==="number"&&isNaN(r))return;o==="number"&&!v.cssNumber[a]&&(r+="px");if(!u||!("set"in u)||(r=u.set(e,r,i))!==t)try{f[n]=r}catch(l){}},css:function(e,n,r,i){var s,o,u,a=v.camelCase(n);return n=v.cssProps[a]||(v.cssProps[a]=Qt(e.style,a)),u=v.cssHooks[n]||v.cssHooks[a],u&&"get"in u&&(s=u.get(e,!0,i)),s===t&&(s=Dt(e,n)),s==="normal"&&n in Vt&&(s=Vt[n]),r||i!==t?(o=parseFloat(s),r||v.isNumeric(o)?o||0:s):s},swap:function(e,t,n){var r,i,s={};for(i in t)s[i]=e.style[i],e.style[i]=t[i];r=n.call(e);for(i in t)e.style[i]=s[i];return r}}),e.getComputedStyle?Dt=function(t,n){var r,i,s,o,u=e.getComputedStyle(t,null),a=t.style;return u&&(r=u.getPropertyValue(n)||u[n],r===""&&!v.contains(t.ownerDocument,t)&&(r=v.style(t,n)),Ut.test(r)&&qt.test(n)&&(i=a.width,s=a.minWidth,o=a.maxWidth,a.minWidth=a.maxWidth=a.width=r,r=u.width,a.width=i,a.minWidth=s,a.maxWidth=o)),r}:i.documentElement.currentStyle&&(Dt=function(e,t){var n,r,i=e.currentStyle&&e.currentStyle[t],s=e.style;return i==null&&s&&s[t]&&(i=s[t]),Ut.test(i)&&!Ft.test(t)&&(n=s.left,r=e.runtimeStyle&&e.runtimeStyle.left,r&&(e.runtimeStyle.left=e.currentStyle.left),s.left=t==="fontSize"?"1em":i,i=s.pixelLeft+"px",s.left=n,r&&(e.runtimeStyle.left=r)),i===""?"auto":i}),v.each(["height","width"],function(e,t){v.cssHooks[t]={get:function(e,n,r){if(n)return e.offsetWidth===0&&It.test(Dt(e,"display"))?v.swap(e,Xt,function(){return tn(e,t,r)}):tn(e,t,r)},set:function(e,n,r){return Zt(e,n,r?en(e,t,r,v.support.boxSizing&&v.css(e,"boxSizing")==="border-box"):0)}}}),v.support.opacity||(v.cssHooks.opacity={get:function(e,t){return jt.test((t&&e.currentStyle?e.currentStyle.filter:e.style.filter)||"")?.01*parseFloat(RegExp.$1)+"":t?"1":""},set:function(e,t){var n=e.style,r=e.currentStyle,i=v.isNumeric(t)?"alpha(opacity="+t*100+")":"",s=r&&r.filter||n.filter||"";n.zoom=1;if(t>=1&&v.trim(s.replace(Bt,""))===""&&n.removeAttribute){n.removeAttribute("filter");if(r&&!r.filter)return}n.filter=Bt.test(s)?s.replace(Bt,i):s+" "+i}}),v(function(){v.support.reliableMarginRight||(v.cssHooks.marginRight={get:function(e,t){return v.swap(e,{display:"inline-block"},function(){if(t)return Dt(e,"marginRight")})}}),!v.support.pixelPosition&&v.fn.position&&v.each(["top","left"],function(e,t){v.cssHooks[t]={get:function(e,n){if(n){var r=Dt(e,t);return Ut.test(r)?v(e).position()[t]+"px":r}}}})}),v.expr&&v.expr.filters&&(v.expr.filters.hidden=function(e){return e.offsetWidth===0&&e.offsetHeight===0||!v.support.reliableHiddenOffsets&&(e.style&&e.style.display||Dt(e,"display"))==="none"},v.expr.filters.visible=function(e){return!v.expr.filters.hidden(e)}),v.each({margin:"",padding:"",border:"Width"},function(e,t){v.cssHooks[e+t]={expand:function(n){var r,i=typeof n=="string"?n.split(" "):[n],s={};for(r=0;r<4;r++)s[e+$t[r]+t]=i[r]||i[r-2]||i[0];return s}},qt.test(e)||(v.cssHooks[e+t].set=Zt)});var rn=/%20/g,sn=/\[\]$/,on=/\r?\n/g,un=/^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,an=/^(?:select|textarea)/i;v.fn.extend({serialize:function(){return v.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?v.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||an.test(this.nodeName)||un.test(this.type))}).map(function(e,t){var n=v(this).val();return n==null?null:v.isArray(n)?v.map(n,function(e,n){return{name:t.name,value:e.replace(on,"\r\n")}}):{name:t.name,value:n.replace(on,"\r\n")}}).get()}}),v.param=function(e,n){var r,i=[],s=function(e,t){t=v.isFunction(t)?t():t==null?"":t,i[i.length]=encodeURIComponent(e)+"="+encodeURIComponent(t)};n===t&&(n=v.ajaxSettings&&v.ajaxSettings.traditional);if(v.isArray(e)||e.jquery&&!v.isPlainObject(e))v.each(e,function(){s(this.name,this.value)});else for(r in e)fn(r,e[r],n,s);return i.join("&").replace(rn,"+")};var ln,cn,hn=/#.*$/,pn=/^(.*?):[ \t]*([^\r\n]*)\r?$/mg,dn=/^(?:about|app|app\-storage|.+\-extension|file|res|widget):$/,vn=/^(?:GET|HEAD)$/,mn=/^\/\//,gn=/\?/,yn=/)<[^<]*)*<\/script>/gi,bn=/([?&])_=[^&]*/,wn=/^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+)|)|)/,En=v.fn.load,Sn={},xn={},Tn=["*/"]+["*"];try{cn=s.href}catch(Nn){cn=i.createElement("a"),cn.href="",cn=cn.href}ln=wn.exec(cn.toLowerCase())||[],v.fn.load=function(e,n,r){if(typeof e!="string"&&En)return En.apply(this,arguments);if(!this.length)return this;var i,s,o,u=this,a=e.indexOf(" ");return a>=0&&(i=e.slice(a,e.length),e=e.slice(0,a)),v.isFunction(n)?(r=n,n=t):n&&typeof n=="object"&&(s="POST"),v.ajax({url:e,type:s,dataType:"html",data:n,complete:function(e,t){r&&u.each(r,o||[e.responseText,t,e])}}).done(function(e){o=arguments,u.html(i?v("
").append(e.replace(yn,"")).find(i):e)}),this},v.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(e,t){v.fn[t]=function(e){return this.on(t,e)}}),v.each(["get","post"],function(e,n){v[n]=function(e,r,i,s){return v.isFunction(r)&&(s=s||i,i=r,r=t),v.ajax({type:n,url:e,data:r,success:i,dataType:s})}}),v.extend({getScript:function(e,n){return v.get(e,t,n,"script")},getJSON:function(e,t,n){return v.get(e,t,n,"json")},ajaxSetup:function(e,t){return t?Ln(e,v.ajaxSettings):(t=e,e=v.ajaxSettings),Ln(e,t),e},ajaxSettings:{url:cn,isLocal:dn.test(ln[1]),global:!0,type:"GET",contentType:"application/x-www-form-urlencoded; charset=UTF-8",processData:!0,async:!0,accepts:{xml:"application/xml, text/xml",html:"text/html",text:"text/plain",json:"application/json, text/javascript","*":Tn},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":e.String,"text html":!0,"text json":v.parseJSON,"text xml":v.parseXML},flatOptions:{context:!0,url:!0}},ajaxPrefilter:Cn(Sn),ajaxTransport:Cn(xn),ajax:function(e,n){function T(e,n,s,a){var l,y,b,w,S,T=n;if(E===2)return;E=2,u&&clearTimeout(u),o=t,i=a||"",x.readyState=e>0?4:0,s&&(w=An(c,x,s));if(e>=200&&e<300||e===304)c.ifModified&&(S=x.getResponseHeader("Last-Modified"),S&&(v.lastModified[r]=S),S=x.getResponseHeader("Etag"),S&&(v.etag[r]=S)),e===304?(T="notmodified",l=!0):(l=On(c,w),T=l.state,y=l.data,b=l.error,l=!b);else{b=T;if(!T||e)T="error",e<0&&(e=0)}x.status=e,x.statusText=(n||T)+"",l?d.resolveWith(h,[y,T,x]):d.rejectWith(h,[x,T,b]),x.statusCode(g),g=t,f&&p.trigger("ajax"+(l?"Success":"Error"),[x,c,l?y:b]),m.fireWith(h,[x,T]),f&&(p.trigger("ajaxComplete",[x,c]),--v.active||v.event.trigger("ajaxStop"))}typeof e=="object"&&(n=e,e=t),n=n||{};var r,i,s,o,u,a,f,l,c=v.ajaxSetup({},n),h=c.context||c,p=h!==c&&(h.nodeType||h instanceof v)?v(h):v.event,d=v.Deferred(),m=v.Callbacks("once memory"),g=c.statusCode||{},b={},w={},E=0,S="canceled",x={readyState:0,setRequestHeader:function(e,t){if(!E){var n=e.toLowerCase();e=w[n]=w[n]||e,b[e]=t}return this},getAllResponseHeaders:function(){return E===2?i:null},getResponseHeader:function(e){var n;if(E===2){if(!s){s={};while(n=pn.exec(i))s[n[1].toLowerCase()]=n[2]}n=s[e.toLowerCase()]}return n===t?null:n},overrideMimeType:function(e){return E||(c.mimeType=e),this},abort:function(e){return e=e||S,o&&o.abort(e),T(0,e),this}};d.promise(x),x.success=x.done,x.error=x.fail,x.complete=m.add,x.statusCode=function(e){if(e){var t;if(E<2)for(t in e)g[t]=[g[t],e[t]];else t=e[x.status],x.always(t)}return this},c.url=((e||c.url)+"").replace(hn,"").replace(mn,ln[1]+"//"),c.dataTypes=v.trim(c.dataType||"*").toLowerCase().split(y),c.crossDomain==null&&(a=wn.exec(c.url.toLowerCase()),c.crossDomain=!(!a||a[1]===ln[1]&&a[2]===ln[2]&&(a[3]||(a[1]==="http:"?80:443))==(ln[3]||(ln[1]==="http:"?80:443)))),c.data&&c.processData&&typeof c.data!="string"&&(c.data=v.param(c.data,c.traditional)),kn(Sn,c,n,x);if(E===2)return x;f=c.global,c.type=c.type.toUpperCase(),c.hasContent=!vn.test(c.type),f&&v.active++===0&&v.event.trigger("ajaxStart");if(!c.hasContent){c.data&&(c.url+=(gn.test(c.url)?"&":"?")+c.data,delete c.data),r=c.url;if(c.cache===!1){var N=v.now(),C=c.url.replace(bn,"$1_="+N);c.url=C+(C===c.url?(gn.test(c.url)?"&":"?")+"_="+N:"")}}(c.data&&c.hasContent&&c.contentType!==!1||n.contentType)&&x.setRequestHeader("Content-Type",c.contentType),c.ifModified&&(r=r||c.url,v.lastModified[r]&&x.setRequestHeader("If-Modified-Since",v.lastModified[r]),v.etag[r]&&x.setRequestHeader("If-None-Match",v.etag[r])),x.setRequestHeader("Accept",c.dataTypes[0]&&c.accepts[c.dataTypes[0]]?c.accepts[c.dataTypes[0]]+(c.dataTypes[0]!=="*"?", "+Tn+"; q=0.01":""):c.accepts["*"]);for(l in c.headers)x.setRequestHeader(l,c.headers[l]);if(!c.beforeSend||c.beforeSend.call(h,x,c)!==!1&&E!==2){S="abort";for(l in{success:1,error:1,complete:1})x[l](c[l]);o=kn(xn,c,n,x);if(!o)T(-1,"No Transport");else{x.readyState=1,f&&p.trigger("ajaxSend",[x,c]),c.async&&c.timeout>0&&(u=setTimeout(function(){x.abort("timeout")},c.timeout));try{E=1,o.send(b,T)}catch(k){if(!(E<2))throw k;T(-1,k)}}return x}return x.abort()},active:0,lastModified:{},etag:{}});var Mn=[],_n=/\?/,Dn=/(=)\?(?=&|$)|\?\?/,Pn=v.now();v.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var e=Mn.pop()||v.expando+"_"+Pn++;return this[e]=!0,e}}),v.ajaxPrefilter("json jsonp",function(n,r,i){var s,o,u,a=n.data,f=n.url,l=n.jsonp!==!1,c=l&&Dn.test(f),h=l&&!c&&typeof a=="string"&&!(n.contentType||"").indexOf("application/x-www-form-urlencoded")&&Dn.test(a);if(n.dataTypes[0]==="jsonp"||c||h)return s=n.jsonpCallback=v.isFunction(n.jsonpCallback)?n.jsonpCallback():n.jsonpCallback,o=e[s],c?n.url=f.replace(Dn,"$1"+s):h?n.data=a.replace(Dn,"$1"+s):l&&(n.url+=(_n.test(f)?"&":"?")+n.jsonp+"="+s),n.converters["script json"]=function(){return u||v.error(s+" was not called"),u[0]},n.dataTypes[0]="json",e[s]=function(){u=arguments},i.always(function(){e[s]=o,n[s]&&(n.jsonpCallback=r.jsonpCallback,Mn.push(s)),u&&v.isFunction(o)&&o(u[0]),u=o=t}),"script"}),v.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/javascript|ecmascript/},converters:{"text script":function(e){return v.globalEval(e),e}}}),v.ajaxPrefilter("script",function(e){e.cache===t&&(e.cache=!1),e.crossDomain&&(e.type="GET",e.global=!1)}),v.ajaxTransport("script",function(e){if(e.crossDomain){var n,r=i.head||i.getElementsByTagName("head")[0]||i.documentElement;return{send:function(s,o){n=i.createElement("script"),n.async="async",e.scriptCharset&&(n.charset=e.scriptCharset),n.src=e.url,n.onload=n.onreadystatechange=function(e,i){if(i||!n.readyState||/loaded|complete/.test(n.readyState))n.onload=n.onreadystatechange=null,r&&n.parentNode&&r.removeChild(n),n=t,i||o(200,"success")},r.insertBefore(n,r.firstChild)},abort:function(){n&&n.onload(0,1)}}}});var Hn,Bn=e.ActiveXObject?function(){for(var e in Hn)Hn[e](0,1)}:!1,jn=0;v.ajaxSettings.xhr=e.ActiveXObject?function(){return!this.isLocal&&Fn()||In()}:Fn,function(e){v.extend(v.support,{ajax:!!e,cors:!!e&&"withCredentials"in e})}(v.ajaxSettings.xhr()),v.support.ajax&&v.ajaxTransport(function(n){if(!n.crossDomain||v.support.cors){var r;return{send:function(i,s){var o,u,a=n.xhr();n.username?a.open(n.type,n.url,n.async,n.username,n.password):a.open(n.type,n.url,n.async);if(n.xhrFields)for(u in n.xhrFields)a[u]=n.xhrFields[u];n.mimeType&&a.overrideMimeType&&a.overrideMimeType(n.mimeType),!n.crossDomain&&!i["X-Requested-With"]&&(i["X-Requested-With"]="XMLHttpRequest");try{for(u in i)a.setRequestHeader(u,i[u])}catch(f){}a.send(n.hasContent&&n.data||null),r=function(e,i){var u,f,l,c,h;try{if(r&&(i||a.readyState===4)){r=t,o&&(a.onreadystatechange=v.noop,Bn&&delete Hn[o]);if(i)a.readyState!==4&&a.abort();else{u=a.status,l=a.getAllResponseHeaders(),c={},h=a.responseXML,h&&h.documentElement&&(c.xml=h);try{c.text=a.responseText}catch(p){}try{f=a.statusText}catch(p){f=""}!u&&n.isLocal&&!n.crossDomain?u=c.text?200:404:u===1223&&(u=204)}}}catch(d){i||s(-1,d)}c&&s(u,f,c,l)},n.async?a.readyState===4?setTimeout(r,0):(o=++jn,Bn&&(Hn||(Hn={},v(e).unload(Bn)),Hn[o]=r),a.onreadystatechange=r):r()},abort:function(){r&&r(0,1)}}}});var qn,Rn,Un=/^(?:toggle|show|hide)$/,zn=new RegExp("^(?:([-+])=|)("+m+")([a-z%]*)$","i"),Wn=/queueHooks$/,Xn=[Gn],Vn={"*":[function(e,t){var n,r,i=this.createTween(e,t),s=zn.exec(t),o=i.cur(),u=+o||0,a=1,f=20;if(s){n=+s[2],r=s[3]||(v.cssNumber[e]?"":"px");if(r!=="px"&&u){u=v.css(i.elem,e,!0)||n||1;do a=a||".5",u/=a,v.style(i.elem,e,u+r);while(a!==(a=i.cur()/o)&&a!==1&&--f)}i.unit=r,i.start=u,i.end=s[1]?u+(s[1]+1)*n:n}return i}]};v.Animation=v.extend(Kn,{tweener:function(e,t){v.isFunction(e)?(t=e,e=["*"]):e=e.split(" ");var n,r=0,i=e.length;for(;r-1,f={},l={},c,h;a?(l=i.position(),c=l.top,h=l.left):(c=parseFloat(o)||0,h=parseFloat(u)||0),v.isFunction(t)&&(t=t.call(e,n,s)),t.top!=null&&(f.top=t.top-s.top+c),t.left!=null&&(f.left=t.left-s.left+h),"using"in t?t.using.call(e,f):i.css(f)}},v.fn.extend({position:function(){if(!this[0])return;var e=this[0],t=this.offsetParent(),n=this.offset(),r=er.test(t[0].nodeName)?{top:0,left:0}:t.offset();return n.top-=parseFloat(v.css(e,"marginTop"))||0,n.left-=parseFloat(v.css(e,"marginLeft"))||0,r.top+=parseFloat(v.css(t[0],"borderTopWidth"))||0,r.left+=parseFloat(v.css(t[0],"borderLeftWidth"))||0,{top:n.top-r.top,left:n.left-r.left}},offsetParent:function(){return this.map(function(){var e=this.offsetParent||i.body;while(e&&!er.test(e.nodeName)&&v.css(e,"position")==="static")e=e.offsetParent;return e||i.body})}}),v.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(e,n){var r=/Y/.test(n);v.fn[e]=function(i){return v.access(this,function(e,i,s){var o=tr(e);if(s===t)return o?n in o?o[n]:o.document.documentElement[i]:e[i];o?o.scrollTo(r?v(o).scrollLeft():s,r?s:v(o).scrollTop()):e[i]=s},e,i,arguments.length,null)}}),v.each({Height:"height",Width:"width"},function(e,n){v.each({padding:"inner"+e,content:n,"":"outer"+e},function(r,i){v.fn[i]=function(i,s){var o=arguments.length&&(r||typeof i!="boolean"),u=r||(i===!0||s===!0?"margin":"border");return v.access(this,function(n,r,i){var s;return v.isWindow(n)?n.document.documentElement["client"+e]:n.nodeType===9?(s=n.documentElement,Math.max(n.body["scroll"+e],s["scroll"+e],n.body["offset"+e],s["offset"+e],s["client"+e])):i===t?v.css(n,r,i,u):v.style(n,r,i,u)},n,o?i:t,o,null)}})}),e.jQuery=e.$=v,typeof define=="function"&&define.amd&&define.amd.jQuery&&define("jquery",[],function(){return v})})(window); -------------------------------------------------------------------------------- /spec/vendor/mocha.css: -------------------------------------------------------------------------------- 1 | @charset "UTF-8"; 2 | body { 3 | font: 20px/1.5 "Helvetica Neue", Helvetica, Arial, sans-serif; 4 | padding: 60px 50px; 5 | } 6 | 7 | #mocha ul, #mocha li { 8 | margin: 0; 9 | padding: 0; 10 | } 11 | 12 | #mocha ul { 13 | list-style: none; 14 | } 15 | 16 | #mocha h1, #mocha h2 { 17 | margin: 0; 18 | } 19 | 20 | #mocha h1 { 21 | margin-top: 15px; 22 | font-size: 1em; 23 | font-weight: 200; 24 | } 25 | 26 | #mocha h1 a { 27 | text-decoration: none; 28 | color: inherit; 29 | } 30 | 31 | #mocha h1 a:hover { 32 | text-decoration: underline; 33 | } 34 | 35 | #mocha .suite .suite h1 { 36 | margin-top: 0; 37 | font-size: .8em; 38 | } 39 | 40 | .hidden { 41 | display: none; 42 | } 43 | 44 | #mocha h2 { 45 | font-size: 12px; 46 | font-weight: normal; 47 | cursor: pointer; 48 | } 49 | 50 | #mocha .suite { 51 | margin-left: 15px; 52 | } 53 | 54 | #mocha .test { 55 | margin-left: 15px; 56 | } 57 | 58 | #mocha .test.pending:hover h2::after { 59 | content: '(pending)'; 60 | font-family: arial; 61 | } 62 | 63 | #mocha .test.pass.medium .duration { 64 | background: #C09853; 65 | } 66 | 67 | #mocha .test.pass.slow .duration { 68 | background: #B94A48; 69 | } 70 | 71 | #mocha .test.pass::before { 72 | content: '✓'; 73 | font-size: 12px; 74 | display: block; 75 | float: left; 76 | margin-right: 5px; 77 | color: #00d6b2; 78 | } 79 | 80 | #mocha .test.pass .duration { 81 | font-size: 9px; 82 | margin-left: 5px; 83 | padding: 2px 5px; 84 | color: white; 85 | -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.2); 86 | -moz-box-shadow: inset 0 1px 1px rgba(0,0,0,.2); 87 | box-shadow: inset 0 1px 1px rgba(0,0,0,.2); 88 | -webkit-border-radius: 5px; 89 | -moz-border-radius: 5px; 90 | -ms-border-radius: 5px; 91 | -o-border-radius: 5px; 92 | border-radius: 5px; 93 | } 94 | 95 | #mocha .test.pass.fast .duration { 96 | display: none; 97 | } 98 | 99 | #mocha .test.pending { 100 | color: #0b97c4; 101 | } 102 | 103 | #mocha .test.pending::before { 104 | content: '◦'; 105 | color: #0b97c4; 106 | } 107 | 108 | #mocha .test.fail { 109 | color: #c00; 110 | } 111 | 112 | #mocha .test.fail pre { 113 | color: black; 114 | } 115 | 116 | #mocha .test.fail::before { 117 | content: '✖'; 118 | font-size: 12px; 119 | display: block; 120 | float: left; 121 | margin-right: 5px; 122 | color: #c00; 123 | } 124 | 125 | #mocha .test pre.error { 126 | color: #c00; 127 | max-height: 300px; 128 | overflow: auto; 129 | } 130 | 131 | #mocha .test pre { 132 | display: inline-block; 133 | font: 12px/1.5 monaco, monospace; 134 | margin: 5px; 135 | padding: 15px; 136 | border: 1px solid #eee; 137 | border-bottom-color: #ddd; 138 | -webkit-border-radius: 3px; 139 | -webkit-box-shadow: 0 1px 3px #eee; 140 | -moz-border-radius: 3px; 141 | -moz-box-shadow: 0 1px 3px #eee; 142 | } 143 | 144 | #mocha .test h2 { 145 | position: relative; 146 | } 147 | 148 | #mocha .test a.replay { 149 | position: absolute; 150 | top: 3px; 151 | right: -20px; 152 | text-decoration: none; 153 | vertical-align: middle; 154 | display: block; 155 | width: 15px; 156 | height: 15px; 157 | line-height: 15px; 158 | text-align: center; 159 | background: #eee; 160 | font-size: 15px; 161 | -moz-border-radius: 15px; 162 | border-radius: 15px; 163 | -webkit-transition: opacity 200ms; 164 | -moz-transition: opacity 200ms; 165 | transition: opacity 200ms; 166 | opacity: 0.2; 167 | color: #888; 168 | } 169 | 170 | #mocha .test:hover a.replay { 171 | opacity: 1; 172 | } 173 | 174 | #mocha-report.pass .test.fail { 175 | display: none; 176 | } 177 | 178 | #mocha-report.fail .test.pass { 179 | display: none; 180 | } 181 | 182 | #mocha-error { 183 | color: #c00; 184 | font-size: 1.5 em; 185 | font-weight: 100; 186 | letter-spacing: 1px; 187 | } 188 | 189 | #mocha-stats { 190 | position: fixed; 191 | top: 15px; 192 | right: 10px; 193 | font-size: 12px; 194 | margin: 0; 195 | color: #888; 196 | } 197 | 198 | #mocha-stats .progress { 199 | float: right; 200 | padding-top: 0; 201 | } 202 | 203 | #mocha-stats em { 204 | color: black; 205 | } 206 | 207 | #mocha-stats a { 208 | text-decoration: none; 209 | color: inherit; 210 | } 211 | 212 | #mocha-stats a:hover { 213 | border-bottom: 1px solid #eee; 214 | } 215 | 216 | #mocha-stats li { 217 | display: inline-block; 218 | margin: 0 5px; 219 | list-style: none; 220 | padding-top: 11px; 221 | } 222 | 223 | code .comment { color: #ddd } 224 | code .init { color: #2F6FAD } 225 | code .string { color: #5890AD } 226 | code .keyword { color: #8A6343 } 227 | code .number { color: #2F6FAD } 228 | -------------------------------------------------------------------------------- /testem.yml: -------------------------------------------------------------------------------- 1 | framework: mocha 2 | test_page: spec/index.html 3 | launch_in_dev: [Chrome, Firefox, PhantomJS] 4 | port: 1221 --------------------------------------------------------------------------------